home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 3 / Info_Mac_1994-01.iso / Compression / Mcvert 2.1.5 < prev    next >
Internet Message Format  |  1993-12-30  |  154KB

  1. From: jskud@wv.MENTORG.COM (Joseph Skudlarek)
  2. Date: Mon, 15 Nov 93 23:22:54 -0800
  3. Subject: mcvert-215.shar
  4.  
  5. mcvert converts among Macintosh file formats used for file interchange,
  6. including BinHex 4.0 (.hqx) and MacBinary (.bin).  mcvert is written
  7. in C and runs on many popular UNIX boxes.  See mcvert.1/mcvert.man
  8. (the man page) for program details.  See README for how to build mcvert.
  9.  
  10. Please replace mcvert-214.shar with mcvert-215.shar, which follows.
  11. It appears that mcvert-214.shar had long lines wrapped, which damaged
  12. the archive's integrity; and when extracted, an invalid C file was
  13. created.  Now all lines in the archvie are 80 characters or less (tab
  14. counts as one character).
  15.  
  16. Thanks to Robert Hagopian (rhagopia@terminator.rs.itd.umich.edu) and
  17. to L L Campbell (campbell@brahms.udel.edu) for bringing this problem
  18. to my attention.
  19.  
  20. #!/bin/sh
  21. # This is a shell archive (produced by shar 3.50)
  22. # To extract the files from this archive, save it to a file, remove
  23. # everything above the "!/bin/sh" line above, and type "sh file_name".
  24. #
  25. # made 11/16/1993 06:05 UTC by jskud@zigzag
  26. # Source directory /tmp_mnt/user/jskud/notes/info-mac/mcvert
  27. #
  28. # existing files will NOT be overwritten unless -c is specified
  29. #
  30. # This shar contains:
  31. # length  mode       name
  32. # ------ ---------- ------------------------------------------
  33. #  44551 -r--r--r-- mcvert.c
  34. #  28300 -r--r--r-- hqxify.c
  35. #   6868 -r--r--r-- unpack.c
  36. #   9956 -r--r--r-- mactypes.h
  37. #   2811 -r--r--r-- Makefile
  38. #    842 -r--r--r-- README
  39. #   7655 -r--r--r-- README-conversion
  40. #  13179 -r--r--r-- mcvert.idraw
  41. #  13789 -r--r--r-- mcvert.1
  42. #  16929 -rw-r--r-- mcvert.man
  43. #
  44. # ============= mcvert.c ==============
  45. if test -f 'mcvert.c' -a X"$1" != X"-c"; then
  46.     echo 'x - skipping mcvert.c (File already exists)'
  47. else
  48. echo 'x - extracting mcvert.c (Text)'
  49. sed 's/^X//' << 'SHAR_EOF' > 'mcvert.c' &&
  50. /**
  51. X * mcvert.c - version 1.05 - 10 January, 1990
  52. X * Written by Doug Moore - Rice University - dougm@rice.edu - April '87
  53. X
  54. X * Sun bug fixes, assorted stuff - Jim Sasaki, March '89
  55. X
  56. X * Changed default max_line_size from 2000 to unlimited -
  57. X *                                           Doug Moore, April, '89
  58. X
  59. X * Sun 3/60 doesn't like odd-sized structs.  Bug fixed - Doug Moore, April, '89
  60. X *                                              - aided by Spencer W. Thomas
  61. X
  62. X * Didn't handle properly many hqx files combined in one file.  Bug fixed -
  63. X *                                           Doug Moore, June, '89
  64. X
  65. X * Modified to handle MacBinaryII specification. Jim Van Verth, Sept, '89
  66. X
  67. X * Fixed a bug when there are blank lines in hqx data, as happens when newline
  68. X * get translated to CRLF and then to \n\n, common for some file transfers.
  69. X * The last hqx line would be lost if the previous line was blank or junk.
  70. X *    Glenn Trewitt, Stanford University, 1990    (1.05)
  71. X
  72. X * Fixed a bug that occurred when extracting data or resource
  73. X * forks on a Sun 4.  It was a byte alignment problem.
  74. X * Rick Zaccone, zaccone@bucknell.edu.  April 1991.  Version 1.6
  75. X
  76. X * Fixed:
  77. X *   Sent all "Converting ... " lines to stdout instead of stderr
  78. X *   Changed mactypes.h for HP-UX systems
  79. X *      Alan Danziger, aland@cs.brandeis.edu.  October 1991. Version 1.6.5
  80. X
  81. X * ----------------------------------------------------------------------------
  82. X * External
  83. X * -----
  84. X * Fixed buffering bug when converting very small MacBinary files to hqx files.
  85. X * Provide helpful usage line.
  86. X * Control "Converting ... " lines separately with -S flag.
  87. X * Make encoding and decoding consistent by ignoring locked and init flags.
  88. X * Clean up some error messages; check for more errors; provide errno on error.
  89. X * Updated the man page.
  90. X * -----
  91. X * Internal
  92. X * -----
  93. X * Reformat source (sorry, local standard used by tools is tab space == 3)
  94. X * Remove compiler warning messages.
  95. X * Rename some variables.
  96. X * Added some comments to code.
  97. X * Added some offsets to struct definitions.
  98. X * Since the makefile has compilation flags,
  99. X *    make the compiles depend on the Makefile.
  100. X * -----
  101. X * Thanks to all who have gone before for creating, maintaining,
  102. X * improving, and providing this program and documentation.
  103. X * -----
  104. X * Joseph Skudlarek  Mentor Graphics  8005 SW Boeckman Rd  Wilsonville OR 97070
  105. X * {Jskud@std.mentorg.com,Joseph_Skudlarek@mentorg.com}
  106. X * ...{uunet,nosun,sequent,attunix,apollo}!mntgfx!Jskud
  107. X * Version 1.70 09Jul92
  108. X * ----------------------------------------------------------------------------
  109. X
  110. X * ----------------------------------------------------------------------------
  111. X * External
  112. X * -----
  113. X * Added -V (Verbose) option (includes debugging information).
  114. X * Fixed bug converting hqx to MacBinary if last line is ":".
  115. X * Avoided a silent error and quick exit situation.
  116. X * -----
  117. X * Internal
  118. X * -----
  119. X * Got rid of almost all lint (SunOS and HP-UX) error messages.
  120. X * Compiled on SunOs, HP-UX, DomainOS.
  121. X * Incorporated Parag Patel <parag@netcom.com> changes for AU/X.
  122. X *    Here's some diffs for really quick cheap hacks to get mcvert to compile
  123. X *    and run under A/UX.  The main problem was that timeb does not exist, so
  124. X *    I added 2 #ifdef TIMEVAL to use the System-V timeval package instead.
  125. X *    The Makefile just has a -DTIMEVAL and a magic -U_SYSV_SOURCE to get
  126. X *    around a pre-defined type "ulong" in sys/types.h (thanks to Apple).
  127. X * Did more code overhauling:
  128. X *    add lots more comments, rename variables, reformat source.
  129. X * Put code in un_hqx to avoid suspected buffering problem.
  130. X * -----
  131. X * Joseph Skudlarek  Mentor Graphics  8005 SW Boeckman Rd  Wilsonville OR 97070
  132. X * (503) 685-1576 (work)
  133. X * {Jskud@std.MENTORG.Com,Joseph_Skudlarek@MENTORG.Com}
  134. X * ...{uunet,nosun,sequent,attunix,apollo}!mntgfx!Jskud
  135. X * Version 1.80 15Jul92
  136. X * ----------------------------------------------------------------------------
  137. X
  138. X * ----------------------------------------------------------------------------
  139. X * External
  140. X * -----
  141. X * Made hqx file scan processing much smarter
  142. X *    so, for example, info-mac/comm/qwk-reader.hqx,
  143. X *    complete with extraneous colons in column one, converts correctly
  144. X *    (problem described by Edward John Sabol <es2j+@andrew.cmu.edu>)
  145. X * Avoid silly perror on usage message (prompted by Edward John Sabol)
  146. X * Improve error message regarding improper format
  147. X * Added more caveats to man page
  148. X * -----
  149. X * Internal
  150. X * -----
  151. X * Fixed typo's in printf lines to pass all expected arguments
  152. X *    (pointed out by Bo Holst-Christensen
  153. X *    [holst@diku.dk/dikubhc1@uts.uni-c.dk/holst@login.dkuug.dk])
  154. X * Tweak Makefile to ease shar creation and special case ulong, not A/UX
  155. X * Add yet more comments and debugging code
  156. X * -----
  157. X * Joseph Skudlarek  Mentor Graphics  8005 SW Boeckman Rd  Wilsonville OR 97070
  158. X * (503) 685-1576 (work)
  159. X * {Jskud@std.MENTORG.Com,Joseph_Skudlarek@MENTORG.Com}
  160. X * ...{uunet,nosun,sequent,attunix,apollo}!mntgfx!Jskud
  161. X * Version 1.82 30Jul92
  162. X * ----------------------------------------------------------------------------
  163. X
  164. X * ----------------------------------------------------------------------------
  165. X * External
  166. X * -----
  167. X * relax exactly 64 characters per incoming hqx file, and
  168. X * handle files without trailing newline, so, eg, 
  169. X *    Telnet2.5docs.sit.hqx now converts correctly
  170. X *       (failure reported by Justin Sullivan <justin@f2.facts.uky.edu>)
  171. X *    now also processes info-mac/app/road-map.hqx correctly
  172. X *       (failure reported by Victor Norton<norton@andy.bgsu.edu>)
  173. X * rework the man page for improved clarity and completeness
  174. X * -----
  175. X * Internal
  176. X * -----
  177. X * avoid warning message from gcc on Sequent Balance mainframe
  178. X *    reported by Justin Sullivan <justin@f2.facts.uky.edu>
  179. X * bump max incoming line length to 2048 from 255
  180. X * add mcvert.ps target to Makefile
  181. X * -----
  182. X * Joseph Skudlarek  Mentor Graphics  8005 SW Boeckman Rd  Wilsonville OR 97070
  183. X * (503) 685-1576 (work)
  184. X * {Jskud@std.MENTORG.Com,Joseph_Skudlarek@MENTORG.Com}
  185. X * ...{uunet,nosun,sequent,attunix,apollo}!mntgfx!Jskud
  186. X * Version 1.83 03Aug92
  187. X * ----------------------------------------------------------------------------
  188. X
  189. X * ----------------------------------------------------------------------------
  190. X * External
  191. X * -----
  192. X * Found and fixed problem with byte ordering plaguing users of
  193. X *    Sequent's Balance running DYNIX, and DEC computers.
  194. X *    The error message looked something like
  195. X *       hqx_to_bin_fork: writing nnn too many bytes
  196. X * Avoid generating debugging info if not to be printed -- cut runtime in half!
  197. X * Generalize and incorporate -I (info) option processing provided by
  198. X *    Paul Franklin, Computer Enginnering, Univ. of Calif., Davis CA 95616
  199. X *    pdfranklin@ucdavis.edu.
  200. X * Added heuristic to avoid false matches in mail headers.
  201. X *    problem expertly characterized, solution beta tested, and subsequent
  202. X *    improvement suggested by "Jim (J.) Lattanzi" <lattanzi@bnr.ca>
  203. X *    so segmented comp.binaries.mac files (either multi-file or concatenated
  204. X *    single file) should now convert correctly.
  205. X * Added -H switch to disable heuristic.
  206. X * Document heuristic in man page.
  207. X * Fixed (long-standing) bug which precluded -p option from being recognized
  208. X *    and verified decompressing and unpacking of PIT files working.
  209. X *    Thanks to Dave Clemans for providing me with a version of PackIt.
  210. X * Add the version to the extened Usage message emitted by the program.
  211. X * Tune the syntax of the summary in the program and man page.
  212. X * Cleaned up spelling mistakes in the man page.
  213. X * -----
  214. X * Internal
  215. X * -----
  216. X * Close all open streams --
  217. X *    fix for binfile by Paul Franklin <pdfranklin@ucdavis.edu>
  218. X * Incorporate changes suggested by Barry_Wolman@transarc.com
  219. X *    to mactypes.h and Makefile for support of IBM RS/6000 running AIX 3.2
  220. X *    reformat Makefile to avoid long option lines
  221. X * Identify the right Makefile lines for Irix too
  222. X *    suggested by Jack Repenning (jackr@dblues.wpd.sgi.com)
  223. X * Clean up the stream handling and add mopen/mclose
  224. X *    avoid unnecessary /dev/null opens
  225. X *    all file open/close/read/write are checked for success
  226. X * Lower lint content on SunOS and HP-UX.
  227. X *    avoiding all "sometimes ignored" lint messages.
  228. X * Improve modularity with mopen/mclose/converting routines.
  229. X * Tune debugging output information.
  230. X * Verify that passes smoke tests on DomainOS/SunOS/HP-UX/ULTRIX.
  231. X * Reformat these comments to avoid tabs.
  232. X * -----
  233. X * Joseph Skudlarek  Mentor Graphics  8005 SW Boeckman Rd  Wilsonville OR 97070
  234. X * (503) 685-1576 (work)
  235. X * {Jskud@std.MENTORG.Com,Joseph_Skudlarek@MENTORG.Com}
  236. X * ...{uunet,nosun,sequent,attunix,apollo}!mntgfx!Jskud
  237. X * Version 1.87 25Sep92
  238. X * ----------------------------------------------------------------------------
  239. X
  240. X * ----------------------------------------------------------------------------
  241. X * External
  242. X * -----
  243. X * Add README file which describes how to configure and compile mcvert
  244. X * Handle multiple BinHex4.0 inputs in a single file again (thanks to
  245. X *    <Mark_Larimer@pigeon.cpg.cdc.com> for pointing out this regression)
  246. X * Emit the MacBinary header if verbose (to get create and modify times)
  247. X * -----
  248. X * Internal
  249. X * -----
  250. X * Rename some variables, create mac2unix (time) routine, more comments
  251. X * Keep lint content low
  252. X * Pull unnecessary include of <net/nh.h> -- avoid breaking AIX 3.1
  253. X * Fix = vs == typo dealing with protect bit
  254. X * -----
  255. X * Joseph Skudlarek  Mentor Graphics  8005 SW Boeckman Rd  Wilsonville OR 97070
  256. X * (503) 685-1576 (work)
  257. X * {Jskud@std.MENTORG.Com,Joseph_Skudlarek@MENTORG.Com}
  258. X * ...{uunet,nosun,sequent,attunix,apollo}!mntgfx!Jskud
  259. X * Version 1.88 08Dec92
  260. X * ----------------------------------------------------------------------------
  261. X
  262. X * ----------------------------------------------------------------------------
  263. X * External
  264. X * -----
  265. X * emit input file names when verbose is enabled
  266. X *    (suggested by franklin@eecs.ucdavis.edu)
  267. X * make it easier to build on AT&T 3B2's
  268. X * -----
  269. X * Internal
  270. X * -----
  271. X * provide compile time switch to avoid bzero and bcopy, and use memset
  272. X *    and memcpy instead (pointed out by linger@drystone.attmail.com, and
  273. X *    requested again by Larry S. Staples <attjp4!lss>)
  274. X * update Makefile to include incantations required for AT&T 3B2's
  275. X * fflush all diagnostic output to ensure correct order when output to a file
  276. X * -----
  277. X * Joseph Skudlarek  Mentor Graphics  8005 SW Boeckman Rd  Wilsonville OR 97070
  278. X * (503) 685-1576 (work)
  279. X * {Jskud@std.MENTORG.Com,Joseph_Skudlarek@MENTORG.Com}
  280. X * ...{uunet,nosun,sequent,attunix,apollo}!mntgfx!Jskud
  281. X * Version 1.89 05Jan93
  282. X * ----------------------------------------------------------------------------
  283. X
  284. X * ----------------------------------------------------------------------------
  285. X * External
  286. X * -----
  287. X * incorporate MAC_FILETYPE support provided by <root@genome.stanford.edu>
  288. X * minor edits to man page
  289. X * -----
  290. X * Internal
  291. X * -----
  292. X * update Makefile to simplify incantations required for AT&T 3B2's
  293. X * -----
  294. X * Joseph Skudlarek  Mentor Graphics  8005 SW Boeckman Rd  Wilsonville OR 97070
  295. X * (503) 685-1576 (work)
  296. X * {Jskud@std.MENTORG.Com,Joseph_Skudlarek@MENTORG.Com}
  297. X * ...{uunet,nosun,sequent,attunix,apollo}!mntgfx!Jskud
  298. X * Version 1.90 04Mar93
  299. X * ----------------------------------------------------------------------------
  300. X
  301. X * ----------------------------------------------------------------------------
  302. X * External
  303. X * -----
  304. X * handle -b (both .data and .rsrc at same time) option
  305. X *    ( -> MacBinary suggested by bb@math.ufl.edu)
  306. X * remove anomalous file extension handling
  307. X *    (suggested by bb@math.ufl.edu)
  308. X * regularize MAC_EDITOR (author) and MAC_FILETYPE (file type) handling
  309. X * detect and report important file format errors
  310. X * emit output file name too
  311. X * revise Usage line
  312. X * massively revise man page to reflect changes and generally overhaul
  313. X * -----
  314. X * Internal
  315. X * -----
  316. X * avoid overwriting internal storage (what a chore!)
  317. X *    for example, mcvert -UI *.hqx used to abort with a segmentation violation
  318. X *    symptom reported by franklin@eecs.ucdavis.edu  Thu Sep 24 16:39:21 1992
  319. X * check return values from all getc/putc operations
  320. X * find and fix ancient bug extracting resource fork from MacBinary format
  321. X * identify failing file in EOF error messages
  322. X * clarify and amend distribution and update restrictions
  323. X * expand disclaimer (patterned after INFO-MAC CD-ROM -- Thx, Cliff and Joe!)
  324. X * -----
  325. X * Joseph Skudlarek  Mentor Graphics  8005 SW Boeckman Rd  Wilsonville OR 97070
  326. X * (503) 685-1576 (work)
  327. X * {Jskud@std.MENTORG.Com,Joseph_Skudlarek@MENTORG.Com}
  328. X * ...{uunet,nosun,sequent,attunix,apollo}!mntgfx!Jskud
  329. X * Version 2.00 28Feb93
  330. X * ----------------------------------------------------------------------------
  331. X
  332. X * ----------------------------------------------------------------------------
  333. X * External
  334. X * -----
  335. X * unixify all relevent output files
  336. X *    (replace suspect characters with _)
  337. X * macify all relevent MacBinary files
  338. X *    (replace suspect chars with -, take first 20 and last 11 if > 31 char)
  339. X *    avoiding Mac file name > 31 chars (Rick Zaccone zaccone@bucknell.edu)
  340. X * always emit the Macintosh file name in the converting messages
  341. X *    since the UNIX file names are now provided by default
  342. X * rework man page to bring it more up to date, added OTHER SOURCES section
  343. X * emit data and rsrc len when printing bin header
  344. X * report the input character, not the mapped character, if avail,
  345. X *    else report mapped value as hex
  346. X * add -VV (Very Verbose) option
  347. X * -----
  348. X * Internal
  349. X * -----
  350. X * distribute mcvert.idraw, a postscript file
  351. X *    describing mcvert options and transformations pictorially,
  352. X *    contributed by Brian Bartholomew - bb@math.ufl.edu
  353. X * create and distribute README-conversion file
  354. X * update Makefile and README to make it more obvious how to build mcvert
  355. X *    problem reported by David Micklethwaite <mickles@cherax.super.csiro.au>
  356. X * make s/S/v/V flag processing serially reusable
  357. X * avoid obsolete ftime on HP-UX, SunOS, DomainOS -- default is now -DTIMEVAL
  358. X *    problem reported by smith@sfu.ca (Richard Smith) and
  359. X *    Adam Harris (harris@cs.uchicago.edu)
  360. X * avoid SGI bug regarding unterminated character constant within #ifdef notdef
  361. X *    problem reported by smith@sfu.ca (Richard Smith)
  362. X * clean up some FILE confusion
  363. X * make the man page work well across platforms
  364. X * re-lint on SunOS and HP-UX
  365. X * add various additional comments
  366. X * -----
  367. X * Joseph Skudlarek  Mentor Graphics  8005 SW Boeckman Rd  Wilsonville OR 97070
  368. X * (503) 685-1576 (work)
  369. X * {Jskud@wv.MentorG.com,Joseph_Skudlarek@MentorG.com}
  370. X * Version 2.09 30Jun93
  371. X * ----------------------------------------------------------------------------
  372. X
  373. X * ----------------------------------------------------------------------------
  374. X * External
  375. X * -----
  376. X * -----
  377. X * Internal
  378. X * -----
  379. X * incorporate SCO UNIX requirements into the Makefile
  380. X *    info from Fred Lenk, Camarillo, CA [fredgl@tecnet1.jcte.jcs.mil]
  381. X * backout intermediate XOBJ cleanup and continue to do what works for AT&T 3B2
  382. X *    belated & current thanks to Larry S. Staples [attjpn!lss@attibr.att.com]
  383. X *    for providing and proofing the working recipe for AT&T 3B2
  384. X * change OTHER SOURCES to OTHER PROGRAMS in man page, and mention programs
  385. X *    which run on the Mac, including CompactPro, StuffIt, and BinHex 4.0
  386. X * ship the formatted ASCII version of the man page for those without nroff
  387. X * -----
  388. X * Joseph Skudlarek  Mentor Graphics  8005 SW Boeckman Rd  Wilsonville OR 97070
  389. X * (503) 685-1576 (work)
  390. X * {Jskud@wv.MentorG.com,Joseph_Skudlarek@MentorG.com}
  391. X * Version 2.12 19Jul93
  392. X * ----------------------------------------------------------------------------
  393. X
  394. X * ----------------------------------------------------------------------------
  395. X * External
  396. X * -----
  397. X * -----
  398. X * Internal
  399. X * -----
  400. X * add StuffIt Expander mention to man page
  401. X * suggest using text (-t|-u) if data is text in the data (-d) description
  402. X * incorporate AIX Makefile improvement provided by
  403. X *    DaviD W. Sanderson (dws@ssec.wisc.edu)
  404. X * -----
  405. X * Joseph Skudlarek  Mentor Graphics  8005 SW Boeckman Rd  Wilsonville OR 97070
  406. X * (503) 685-1576 (work)
  407. X * {Jskud@wv.MentorG.com,Joseph_Skudlarek@MentorG.com}
  408. X * Version 2.13 13Sep93
  409. X * ----------------------------------------------------------------------------
  410. X
  411. X * ----------------------------------------------------------------------------
  412. X * External
  413. X * -----
  414. X * add -P (pipe to stdout) option
  415. X *    capability requested by lentz@rossi.astro.nwu.edu (Robert Lentz)
  416. X * have all info messages go to stderr, not stdout, to faciliate -P
  417. X *    (undo converting msg to stdout from version 1.6.5, dated Oct 1991)
  418. X * update man page to indicate changes
  419. X * -----
  420. X * Internal
  421. X * -----
  422. X * fiddle with info message to make it a bit clearer
  423. X * -----
  424. X * Joseph Skudlarek  Mentor Graphics  8005 SW Boeckman Rd  Wilsonville OR 97070
  425. X * (503) 685-1576 (work)
  426. X * {Jskud@wv.MentorG.com,Joseph_Skudlarek@MentorG.com}
  427. X * Version 2.14 10Nov93
  428. X * ----------------------------------------------------------------------------
  429. X
  430. X * ----------------------------------------------------------------------------
  431. X * External
  432. X * -----
  433. X * -----
  434. X * Internal
  435. X * -----
  436. X * ensure all source line lengths are less than 80
  437. X *    after someone or something wrapped the 2.14 archive,
  438. X *    and it would not compile (split a character string literal)
  439. X *    [recall that shar usually prepends X, which bumps the line length by 1]
  440. X *    [also, this makes editing with emacs at 80 columns a bit better]
  441. X * add check_linelen to Makefile to ensure compliance
  442. X * -----
  443. X * Joseph Skudlarek  Mentor Graphics  8005 SW Boeckman Rd  Wilsonville OR 97070
  444. X * (503) 685-1576 (work)
  445. X * {Jskud@wv.MentorG.com,Joseph_Skudlarek@MentorG.com}
  446. X * Version 2.15 15Nov93
  447. X * ----------------------------------------------------------------------------
  448. X
  449. X * ----------------------------------------------------------------------------
  450. X * This program may be freely distributed for non-profit purposes.  It
  451. X * may not be sold, by itself or as part of a collection of software.
  452. X * However, it may be distributed in source form with large
  453. X * collections of freeware and shareware, such as the INFO-MAC CD-ROM,
  454. X * which charge only a modest fee for publishing, but not selling, the
  455. X * software.  It may be freely modified as long as no modified version
  456. X * is independently distributed.  Modifications of interest to all can
  457. X * be incorporated into the program by sending them to me for
  458. X * inclusion and redistribution, or by releasing an updated mcvert to
  459. X * the info-mac archives.  Parts of the code can be used in other
  460. X * programs.  We hope you find mcvert useful, and enjoy using it.
  461. X * ----------------------------------------------------------------------------
  462. X
  463. X * ----------------------------------------------------------------------------
  464. X * DISCLAIMER -- USE mcvert software AT YOUR OWN RISK
  465. X * This mcvert software is provided "as is" without warrantee of any
  466. X * kind.  The entire risk as to the results and performance of the
  467. X * software is assumed by you, and in no event will we be liable for
  468. X * any consequential, incidental, or indirect damages suffered in the
  469. X * course of using this software.
  470. X * ----------------------------------------------------------------------------
  471. X
  472. X * ----------------------------------------------------------------------------
  473. X * Things that yet could be done:
  474. X * ---
  475. X * handle incoming BinHex4.0 files with ^M instead of ^J
  476. X * (requested by jonathan brecher brecher@husc.harvard.edu 29Mar93)
  477. X *  eg, right now we toss the entire line if it doesn't start with a colon
  478. X *  but the start of the line could be later on, following a ^M
  479. X * check for more file format errors, eg, MacBinary must be multiple of 128
  480. X * option to avoid .text extension on write (Rick Zaccone zaccone@bucknell.edu)
  481. X * check return values from fputs/fprintf
  482. X * provide header heuristic tuning option: set length and/or same sensitivity
  483. X * ----------------------------------------------------------------------------
  484. X */
  485. X
  486. /*
  487. X * Naming
  488. X *        DOWNLOAD
  489. X *            => converting TO MacBinary
  490. X *            => direction == FORWARDS
  491. X *            => use un_* routines (un => UNdo encoding?)
  492. X *        UPLOAD
  493. X *            => converting FROM MacBinary
  494. X *            => direction == BACKWARDS
  495. X *            => use re_* routines (re => Really Encode?)
  496. X */
  497. X
  498. #include "mactypes.h"
  499. X
  500. /* it would be natural to use an enum here, but avoid "fancy" features */
  501. #define HQX 0
  502. #define TEXT 1
  503. #define DATA 2
  504. #define RSRC 3
  505. #define BOTH 5
  506. X
  507. #define FORWARDS 0
  508. #define BACKWARDS 1
  509. X
  510. FILE *devnull;
  511. FILE *convert;
  512. FILE *verbose;
  513. FILE *debug;
  514. int   Debug;
  515. X
  516. char **hqxnames, **hqxnames_left;
  517. char *dir, *ext, *mac_auth, *mac_type;
  518. int translate_eol;
  519. char *maxlines_str;
  520. int maxlines;
  521. X
  522. /* used to skip suspect mail header lines */
  523. int suspect_shorter = 12;
  524. int suspect_same = 1;
  525. X
  526. /* used to avoid writing output files */
  527. int info_only;
  528. X
  529. /* pipe appropriate output -- write to stdout */
  530. int pipe_out;
  531. X
  532. char Usage[] = "\
  533. Usage: %s { [option] ... name ...} ...\n\
  534. X version:\t%4.2f\n\
  535. X default:\t-xDqv\n\
  536. \n\
  537. X option:\n\
  538. \t-x\tBinHex        .hqx  <-> MacBinary\n\
  539. \t-u\tText(trans)   .text <-> MacBinary\n\
  540. \t-h\tHost(as is)   .text <-> MacBinary\n\
  541. \t-d\tData          .data <-> MacBinary\n\
  542. \t-r\tResource      .rsrc <-> MacBinary\n\
  543. \t-b\tBoth    .data .rsrc <-> MacBinary\n\
  544. \n\
  545. \t-D\tDownload       Other -> MacBinary\n\
  546. \t-U\tUpload     MacBinary -> Other\n\
  547. \n\
  548. \t-p\tBinHex -> MacBinary => unpack PIT\n\
  549. \t-q\tdisable unpack PIT\n\
  550. \t-t\ttranslate end-of-line chars (useful with -b)\n\
  551. \n\
  552. \t-I\tInformation only (does not write output files)\n\
  553. \t-P\tPipe output to stdout\n\
  554. \t-s\tsilent\n\
  555. \t-S\tSilent about ``Converting ... '' lines too\n\
  556. \t-v\tverbose\n\
  557. \t-V\tVerbose, includes debugging information\n\
  558. \t-VV\tVery Verbose, includes extra debugging information\n\
  559. \t-H\tdisable skip-legal-but-suspect-lines Heuristic\n\
  560. \n\
  561. Environment:\n\
  562. \tMAC_FILETYPE  \tTEXT|????\tMac file type for Text|other\n\
  563. \tMAC_EDITOR    \tMACA|????\tMac creator (author) for Text|other\n\
  564. \tMAC_EXT       \t.bin     \textension for -D\n\
  565. \tMAC_DLOAD_DIR \t.        \tdirectory for -D\n\
  566. \tMAC_LINE_LIMIT\tnone     \tmaximum line length for -Ux\n\
  567. ";
  568. X
  569. char *cmdname;
  570. X
  571. main(argc, argv)
  572. X    int argc;
  573. X    char **argv;
  574. {
  575. X    char *flags, *getenv();
  576. X    int direction, mode, unpit_flag;
  577. X
  578. X    cmdname = argv[0];
  579. X
  580. X    /* Early error and clean exit if missing arguments */
  581. X    if (argc < 2) {
  582. X        usage();
  583. X        /*NOTREACHED*/
  584. X    }
  585. X
  586. X    devnull = fopen("/dev/null", "w+");
  587. X
  588. X    argv++;
  589. X    argc--;
  590. X
  591. X    convert = stderr;
  592. X    verbose = stderr;
  593. X    debug = devnull;
  594. X    Debug = 0;
  595. X
  596. X    direction = FORWARDS;
  597. X    mode = HQX;
  598. X    unpit_flag = 0;
  599. X
  600. X    mac_type = getenv("MAC_FILETYPE");
  601. X    mac_auth = getenv("MAC_EDITOR");
  602. X
  603. X    if ((ext = getenv("MAC_EXT")) == NULL)
  604. X        ext = ".bin";
  605. X    if ((dir = getenv("MAC_DLOAD_DIR")) == NULL)
  606. X        dir = ".";
  607. X    if ((maxlines_str = getenv("MAC_LINE_LIMIT")) == NULL)
  608. X        maxlines = 0;
  609. X    else {
  610. X        maxlines = atoi(maxlines_str);
  611. X        if (maxlines < MIN_HQX_LINES) {
  612. X            fprintf(stderr, "%s: %s; was %d; reset to %d\n",
  613. X                cmdname,
  614. X                "warning: MAC_LINE_LIMIT too small",
  615. X                maxlines, MIN_HQX_LINES);
  616. X            fflush(stderr);
  617. X            maxlines = MIN_HQX_LINES;
  618. X        }
  619. X    }
  620. X
  621. X    /* Make command line arguments globally accessible */
  622. X    hqxnames = (char **) calloc((unsigned)argc + 1, sizeof(char *));
  623. X    hqxnames_left = hqxnames;
  624. X    while (argc--)
  625. X        *hqxnames_left++ = *argv++;
  626. X
  627. X    /* Flag the end of the list */
  628. X    *hqxnames_left = "-";
  629. X    hqxnames_left = hqxnames;
  630. X
  631. X    /* While not at the end of the list */
  632. X    while (strcmp(*hqxnames_left, "-")) {
  633. X        translate_eol = 0;
  634. X        if (hqxnames_left[0][0] == '-') {
  635. X            flags = *hqxnames_left++;
  636. X            while (*++flags)
  637. X                switch (*flags) {
  638. X                case 'x':
  639. X                    mode = HQX;
  640. X                    break;
  641. X                case 'u':
  642. X                    translate_eol = 1;
  643. X                    mode = TEXT;
  644. X                    break;
  645. X                case 'd':
  646. X                    mode = DATA;
  647. X                    break;
  648. X                case 'r':
  649. X                    mode = RSRC;
  650. X                    break;
  651. X                case 'h':
  652. X                    translate_eol = 0;
  653. X                    mode = TEXT;
  654. X                    break;
  655. X                case 'b':
  656. X                    mode = BOTH;
  657. X                    break;
  658. X                case 't':
  659. X                    translate_eol = 1;
  660. X                    break;
  661. X                case 'D':
  662. X                    direction = FORWARDS;
  663. X                    break;
  664. X                case 'U':
  665. X                    direction = BACKWARDS;
  666. X                    break;
  667. X                case 'q':
  668. X                    unpit_flag = 0;
  669. X                    break;
  670. X                case 'p':
  671. X                    unpit_flag = 1;
  672. X                    break;
  673. X                case 'S':
  674. X                    convert = devnull;
  675. X                    verbose = devnull;
  676. X                    debug = devnull;
  677. X                    Debug = 0;
  678. X                    break;
  679. X                case 's':
  680. X                    convert = stderr;
  681. X                    verbose = devnull;
  682. X                    debug = devnull;
  683. X                    Debug = 0;
  684. X                    break;
  685. X                case 'v':
  686. X                    convert = stderr;
  687. X                    verbose = stderr;
  688. X                    debug = devnull;
  689. X                    Debug = 0;
  690. X                    break;
  691. X                case 'V':
  692. X                    convert = stderr;
  693. X                    verbose = stderr;
  694. X                    debug = stderr;
  695. X                    Debug++;
  696. X                    break;
  697. X                case'H':
  698. X                    suspect_shorter = suspect_same = 0;
  699. X                    break;
  700. X                case 'I':
  701. X                    info_only = 1;
  702. X                    break;
  703. X                case 'P':
  704. X                    pipe_out = 1;
  705. X                    break;
  706. X                default:
  707. X                    usage();
  708. X                    /*NOTREACHED*/
  709. X                }
  710. X        }
  711. X
  712. X        if (direction == BACKWARDS)
  713. X            if (mode == HQX && unpit_flag)
  714. X                re_hqx();      /* no re_pit() yet */
  715. X            else if (mode == HQX)
  716. X                re_hqx();
  717. X            else
  718. X                re_other(mode);
  719. X        else if (mode == HQX)
  720. X            un_hqx(unpit_flag);
  721. X        else
  722. X            un_other(mode);
  723. X    }
  724. X
  725. X    exit(0);
  726. X    /*NOTREACHED*/
  727. }
  728. X
  729. /* An array useful for CRC calculations that use 0x1021 as the "seed" */
  730. word magic[] = {
  731. X    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
  732. X    0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
  733. X    0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
  734. X    0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
  735. X    0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
  736. X    0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
  737. X    0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
  738. X    0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
  739. X    0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
  740. X    0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
  741. X    0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
  742. X    0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
  743. X    0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
  744. X    0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
  745. X    0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
  746. X    0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
  747. X    0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
  748. X    0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
  749. X    0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
  750. X    0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
  751. X    0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
  752. X    0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
  753. X    0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
  754. X    0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
  755. X    0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
  756. X    0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
  757. X    0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
  758. X    0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
  759. X    0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
  760. X    0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
  761. X    0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
  762. X    0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
  763. };
  764. X
  765. X
  766. /*
  767. X * calc_crc() --
  768. X *   Compute the MacBinary II-style CRC for the data pointed to by p, with the
  769. X *   crc seeded to seed.
  770. X *
  771. X *   Modified by Jim Van Verth to use the magic array for efficiency.
  772. X */
  773. short
  774. calc_mb_crc(p, len, seed)
  775. X    unsigned char *p;
  776. X    long len;
  777. X    short seed;
  778. {
  779. X    short hold;        /* crc computed so far */
  780. X    long i;            /* index into data */
  781. X
  782. X    extern unsigned short magic[];    /* the magic array */
  783. X
  784. X    hold = seed;                   /* start with seed */
  785. X    for (i = 0; i < len; i++, p++) {
  786. X        hold ^= (*p << 8);
  787. X        hold = (hold << 8) ^ magic[(unsigned char) (hold >> 8)];
  788. X    }
  789. X
  790. X    return (hold);
  791. }                /* calc_crc() */
  792. X
  793. X
  794. /* Report a fatal error, and exit, never return */
  795. error(msg, name)
  796. X    char msg[], name[];
  797. X
  798. {
  799. X    fprintf(stderr, msg, name);
  800. X    (void)putc('\n', stderr);
  801. X    perror("\nlast perror (may not be relevant)");
  802. X    fprintf(stderr, "%s: exiting\n", cmdname);
  803. X    if (debug == stderr)
  804. X        abort();
  805. X    exit(2);
  806. X    /*NOTREACHED*/
  807. }
  808. X
  809. /* replace illegal Unix characters in file name */
  810. /* make sure host file name doesn't get truncated beyond recognition */
  811. unixify(np)
  812. X    register char *np;
  813. {
  814. X    register ulong c;
  815. X
  816. X    c = strlen(np);
  817. X    if (c > SYSNAMELEN - MAXEXTENSION)
  818. X        c = SYSNAMELEN - MAXEXTENSION;
  819. X    np[c] = '\0';
  820. X
  821. X    /* pre-decrement to match pre-increment within loop */
  822. X    np--;
  823. X    while (c = *++np)
  824. X        /*
  825. X         * that is, ``if control or blank, or slash, or delete or 8bit''
  826. X         * which is the same as ``if blank, slash, or non graphic''
  827. X        */
  828. X        if (c <= ' ' || c == '/' || c > '~')
  829. X            *np = '_';
  830. }
  831. X
  832. /*
  833. X * replace illegal Macintosh characters in file name
  834. X * return resulting length
  835. X *
  836. X * According to Inside Macintosh, IV-90, valid file names
  837. X *    must be [1..31] characters long
  838. X *    must not contain a colon
  839. X *    must contain only printing characters
  840. X */
  841. macify(name, len, translate)
  842. X    char *name;
  843. X    int len;
  844. X    int translate;
  845. {
  846. X    register char *np;
  847. X    register ulong c;
  848. X    char *s, *t;
  849. X    char buffer[SYSNAMELEN];
  850. X
  851. X    /* make a copy to ensure null terminated */
  852. X    strncpy(buffer, name, len);
  853. X    buffer[len] = 0;
  854. X    np = buffer;
  855. X
  856. X    if (len < 1)
  857. X        error("incoming file name is null", "");
  858. X    if (len > 31) {
  859. X        /* too long, so just take first 20 and last 11 */
  860. X        s = np + 20;
  861. X        t = np + len - 11;
  862. X        while (*s++ = *t++)
  863. X            ;
  864. X        len = 31;
  865. X    }
  866. X
  867. X    if (translate) {
  868. X        /* pre-decrement to match pre-increment within loop */
  869. X        np--;
  870. X        while (c = *++np)
  871. X
  872. X         /*
  873. X
  874. X          * Inside Macintosh, I-246, defines the printable characters
  875. X          * for the Macintosh as 0x20 thru 0xD8 less 0x7F.  Yet, the
  876. X          * apple character is above this range, at 0xF0, and the diamond
  877. X          * character is below this range, at 0x13.  And Adobe Garamond
  878. X          * has lots of characgters above 0xD8.
  879. X          * 
  880. X          * On the other hand, we only translate when processing UNIX
  881. X          * file names which are usually ASCII, and ASCII printables are
  882. X          * ' ' <= valid <= '~'.
  883. X          * 
  884. X          * But we want to avoid zapping any characters with the high
  885. X          * order bit set, so 8 bit character users are not zinged.  I've
  886. X          * never used a SONY-NeWS box, but this one's for you.  But how
  887. X          * do we know if/that the UNIX and Macintosh extended characters
  888. X          * are the same?
  889. X          * 
  890. X          * So what to do, what to do?
  891. X          * 
  892. X          * Let's look at it this way: if the UNIX file name has extended
  893. X          * characters in it, they got there for a reason, hopefully on
  894. X          * purpose, and we'll not gratuitously modify them.
  895. X          * 
  896. X          * And it looks like the 6.1.5 Finder running with the 6.0.5
  897. X          * System will translate both control characters and colon into
  898. X          * a dash, but leave the others alone, so so will we.
  899. X          * 
  900. X          * I don't know if MacOS, as opposed to the Finder, behaves
  901. X          * differently, and it's too late tonight to find out.  Maybe
  902. X          * some other time.
  903. X
  904. X      */
  905. X
  906. X          if (c < ' ' || c == ':' || c == '\177')
  907. X                 *np = '-';
  908. X    }
  909. X
  910. X    /* copy the resulting string back in place */
  911. X    strncpy(name, buffer, len);
  912. X
  913. X    return len;
  914. }
  915. X
  916. /*
  917. X * Unix time (GMT since 1-1-1970)
  918. X * Mac time (local since 1-1-1904)
  919. X */
  920. #define MACTIMEDIFF 0x7c25b080    /* Mac time of 00:00:00 GMT, Jan 1, 1970 */
  921. X
  922. /* Convert Unix time to Mac time */
  923. ulong
  924. unix2mac(xtime)
  925. X    ulong xtime;
  926. {
  927. #ifdef TIMEVAL
  928. X    struct timeval t;
  929. X    struct timezone tz;
  930. X
  931. X    gettimeofday(&t, &tz);
  932. X    return long2mac(xtime + MACTIMEDIFF
  933. X       - 60 * (tz.tz_minuteswest - 60 * tz.tz_dsttime));
  934. #else
  935. X    struct timeb tp;
  936. X
  937. X    ftime(&tp);
  938. X    return long2mac(xtime + MACTIMEDIFF
  939. X        - 60 * (tp.timezone - 60 * tp.dstflag));
  940. #endif
  941. }
  942. X
  943. /* Convert Mac time to Unix time */
  944. ulong
  945. mac2unix(xtime)
  946. X    ulong xtime;
  947. {
  948. #ifdef TIMEVAL
  949. X    struct timeval t;
  950. X    struct timezone tz;
  951. X
  952. X    gettimeofday(&t, &tz);
  953. X    return (mac2long(xtime) - MACTIMEDIFF
  954. X       + 60 * (tz.tz_minuteswest - 60 * tz.tz_dsttime));
  955. #else
  956. X    struct timeb tp;
  957. X
  958. X    ftime(&tp);
  959. X    return (mac2long(xtime) - MACTIMEDIFF
  960. X        + 60 * (tp.timezone - 60 * tp.dstflag));
  961. #endif
  962. }
  963. X
  964. /*
  965. X * computes the appropriate output files
  966. X * and the appropriate optional suffixes,
  967. X * all depending on the processing "mode"
  968. X */
  969. X
  970. mode_to_fname_suffix(
  971. X    mode, base_fname, data_fname, data_suffix, rsrc_fname, rsrc_suffix
  972. )
  973. X    int mode;
  974. X    char *base_fname, *data_fname, **data_suffix, *rsrc_fname, **rsrc_suffix;
  975. {
  976. X
  977. X    /* clear names to indicate nothing selected yet */
  978. X    *data_fname = *rsrc_fname = 0;
  979. X
  980. X    switch (mode) {
  981. X    case TEXT:
  982. X        strcpy(data_fname, base_fname);
  983. X        *data_suffix = ".text";
  984. X        break;
  985. X    case DATA:
  986. X        strcpy(data_fname, base_fname);
  987. X        *data_suffix = ".data";
  988. X        break;
  989. X    case RSRC:
  990. X        strcpy(rsrc_fname, base_fname);
  991. X        *rsrc_suffix = ".rsrc";
  992. X        break;
  993. X    case BOTH:
  994. X        strcpy(data_fname, base_fname);
  995. X        strcat(data_fname, ".data");
  996. X        *data_suffix = "";
  997. X        strcpy(rsrc_fname, base_fname);
  998. X        strcat(rsrc_fname, ".rsrc");
  999. X        *rsrc_suffix = "";
  1000. X        break;
  1001. X    default:
  1002. X        error("Internal error: unexpected mode", "");
  1003. X        break;
  1004. X    }
  1005. }
  1006. X
  1007. /*
  1008. X    This procedure basically copies the input file(s) to the output
  1009. X    MacBinary file; in TEXT (translate_eol) mode it changes LF's to
  1010. X    CR's, and in any mode it forges a Mac info header.  Author type
  1011. X    comes from the MAC_EDITOR environment variable if it is defined.
  1012. X */
  1013. X
  1014. un_other(mode)
  1015. X    int mode;
  1016. {
  1017. X    char data_fname[SYSNAMELEN], rsrc_fname[SYSNAMELEN], binfname[SYSNAMELEN];
  1018. X    FILE *data_file, *rsrc_file, *binfile;
  1019. X    char *base_fname, *data_suffix, *rsrc_suffix;
  1020. X    struct stat data_stbuf, rsrc_stbuf;
  1021. X    ulong dlen, rlen, mtim, ctim;
  1022. X
  1023. X    info_header info;
  1024. X    register ulong b;                /* not character, must hold EOF diagnostic */
  1025. X    register ulong nchars;
  1026. X    int extra_chars;
  1027. X    short crc, calc_mb_crc();
  1028. X    long len;
  1029. X
  1030. X    while (hqxnames_left[0][0] != '-') {
  1031. X
  1032. X        if (strlen(*hqxnames_left) >= SYSNAMELEN)
  1033. X            error("Error: specified base file name is too long", "");
  1034. X        base_fname = *hqxnames_left++;
  1035. X
  1036. X        /* set up file names */
  1037. X        mode_to_fname_suffix(mode, base_fname,
  1038. X            data_fname, &data_suffix, rsrc_fname, &rsrc_suffix);
  1039. X
  1040. X        /* process the data file, if requested */
  1041. X        dlen = 0;
  1042. X        if (*data_fname) {
  1043. X            data_file = mopen(data_fname, data_suffix, "r");
  1044. X            if (fstat(fileno(data_file), &data_stbuf))
  1045. X                error("Cannot stat %s", data_fname);
  1046. X            mtim = unix2mac((ulong)data_stbuf.st_mtime);
  1047. X            ctim = unix2mac((ulong)data_stbuf.st_ctime);
  1048. X            dlen = long2mac(data_stbuf.st_size);
  1049. X        }
  1050. X
  1051. X        /* process the rsrc file, if requested */
  1052. X        rlen = 0;
  1053. X        if (*rsrc_fname) {
  1054. X            rsrc_file = mopen(rsrc_fname, rsrc_suffix, "r");
  1055. X            if (fstat(fileno(rsrc_file), &rsrc_stbuf))
  1056. X                error("Cannot stat %s", rsrc_fname);
  1057. X            mtim = unix2mac((ulong)rsrc_stbuf.st_mtime);
  1058. X            ctim = unix2mac((ulong)rsrc_stbuf.st_ctime);
  1059. X            rlen = long2mac(rsrc_stbuf.st_size);
  1060. X        }
  1061. X
  1062. X        /* stuff header data into the info header */
  1063. X
  1064. X        bzero((char*)&info, sizeof(info_header));
  1065. X
  1066. X        info.nlen = strlen(base_fname);
  1067. X        info.nlen = (info.nlen > NAMELEN) ? NAMELEN : info.nlen;
  1068. X        strncpy((char*)info.name, base_fname, (int)info.nlen);
  1069. X
  1070. X        /* now make sure the resulting name is valid */
  1071. X        info.nlen = macify((char*)info.name, (int)info.nlen, 1);
  1072. X
  1073. X        info.uploadvers = '\201';
  1074. X        info.readvers = '\201';
  1075. X
  1076. X        bcopy((char*)&mtim, (char*)info.mtim, 4);
  1077. X        bcopy((char*)&ctim, (char*)info.ctim, 4);
  1078. X
  1079. X        bcopy((char*)&dlen, (char*)info.dlen, 4);
  1080. X        bcopy((char*)&rlen, (char*)info.rlen, 4);
  1081. X
  1082. X        switch (mode) {
  1083. X        case TEXT:
  1084. X            bcopy(mac_type ? mac_type : "TEXT", (char*)info.type, 4);
  1085. X            bcopy(mac_auth ? mac_auth : "MACA", (char*)info.auth, 4);
  1086. X            break;
  1087. X        case DATA:
  1088. X        case RSRC:
  1089. X        case BOTH:
  1090. X            bcopy(mac_type ? mac_type : "????", (char*)info.type, 4);
  1091. X            bcopy(mac_auth ? mac_auth : "????", (char*)info.auth, 4);
  1092. X            break;
  1093. X        default:
  1094. X            error("Internal error: unexpected mode", "");
  1095. X            break;
  1096. X        }
  1097. X
  1098. X        /* calculate CRC */
  1099. X        crc = calc_mb_crc((unsigned char*)&info, 124L, 0);
  1100. X        info.crc[0] = (char) (crc >> 8);
  1101. X        info.crc[1] = (char) crc;
  1102. X
  1103. X        /* Create the .bin file and write the info to it */
  1104. X
  1105. X        len = strlen(dir) + strlen(base_fname) + strlen(ext) + 1;
  1106. X        if (len >= sizeof(binfname))
  1107. X            error("Error: generated binfname would be too long", "");
  1108. X        /*
  1109. X         * base_fname does not need to be unixified --
  1110. X         * was valid coming in
  1111. X         */
  1112. X        sprintf(binfname, "%s/%s%s", dir, base_fname, ext);
  1113. X        binfile = mopen(binfname, "", "w");
  1114. X
  1115. X        converting(info.name, (int)info.nlen, info.type, info.auth);
  1116. X        print_bin_hdr("Creating", &info);
  1117. X        if (1 != fwrite((char*)&info, sizeof(info), 1, binfile))
  1118. X            error("fwrite failed on binfile", "");
  1119. X
  1120. X        /* pump out the data portion */
  1121. X        if (*data_fname) {
  1122. X            nchars = data_stbuf.st_size;
  1123. X            extra_chars = 127 - (nchars + 127) % 128;
  1124. X
  1125. X            if (translate_eol)
  1126. X                while (nchars--) {
  1127. X                    (b = getc(data_file)) == EOF &&
  1128. X                        error("Error: getc failed on data_file", "");
  1129. X                    if (b == LF)
  1130. X                        b = CR;
  1131. X                    putc((char)b, binfile) == EOF &&
  1132. X                        error("Error: putc failed on binfile", "");
  1133. X                }
  1134. X
  1135. X            else
  1136. X                while (nchars--) {
  1137. X                    (b = getc(data_file)) == EOF &&
  1138. X                        error("Error: getc failed on data_file", "");
  1139. X                    putc((char)b, binfile) == EOF &&
  1140. X                        error("Error: putc failed on binfile", "");
  1141. X                }
  1142. X
  1143. X            while (extra_chars--) {
  1144. X                putc(0, binfile) == EOF &&
  1145. X                    error("Error: putc failed on binfile", "");
  1146. X            }
  1147. X
  1148. X            mclose(&data_file, "txtfile");
  1149. X        }
  1150. X
  1151. X        /* pump out the rsrc portion */
  1152. X        if (*rsrc_fname) {
  1153. X            nchars = rsrc_stbuf.st_size;
  1154. X            extra_chars = 127 - (nchars + 127) % 128;
  1155. X
  1156. X            while (nchars--) {
  1157. X                (b = getc(rsrc_file)) == EOF &&
  1158. X                    error("Error: getc failed on rsrc_file", "");
  1159. X                putc((char)b, binfile) == EOF &&
  1160. X                    error("Error: putc failed on binfile", "");
  1161. X            }
  1162. X
  1163. X            while (extra_chars--) {
  1164. X                putc(0, binfile) == EOF &&
  1165. X                    error("Error: putc failed on binfile", "");
  1166. X            }
  1167. X
  1168. X            mclose(&rsrc_file, "txtfile");
  1169. X        }
  1170. X
  1171. X        mclose(&binfile, "binfile");
  1172. X    }
  1173. }
  1174. X
  1175. /*
  1176. X    This procedure basically copies the MacBinary input file to the
  1177. X    output file(s); in TEXT (translate_eol) mode it changes CR's to
  1178. X    LF's, and in any mode it skikps over the Mac info header.
  1179. X */
  1180. X
  1181. re_other(mode)
  1182. X    int mode;
  1183. {
  1184. X    char base_fname[SYSNAMELEN];
  1185. X    char data_fname[SYSNAMELEN], rsrc_fname[SYSNAMELEN], binfname[SYSNAMELEN];
  1186. X    FILE *data_file, *rsrc_file, *binfile;
  1187. X    char *data_suffix, *rsrc_suffix;
  1188. X
  1189. X    info_header info;
  1190. X    register ulong b;
  1191. X    register ulong nchars;
  1192. X    ulong temp;
  1193. X    int extra_chars;
  1194. X    long len;
  1195. X
  1196. X    while (hqxnames_left[0][0] != '-') {
  1197. X
  1198. X        /* suck in the MacBinary header */
  1199. X        if (strlen(*hqxnames_left) >= sizeof(binfname))
  1200. X            error("Error: specified binfname is too long", "");
  1201. X        strcpy(binfname, *hqxnames_left++);
  1202. X        binfile = mopen(binfname, ext, "r");
  1203. X        if (1 != fread((char*)&info, sizeof(info), 1, binfile))
  1204. X            error("fread failed on binfile", "");
  1205. X
  1206. X        /* figure out the target base file name */
  1207. X        if (info.nlen >= NAMELEN)
  1208. X            error("Error: corrupt BinHex data format", "");
  1209. X        strncpy(base_fname, (char*)info.name, (int)info.nlen);
  1210. X        base_fname[info.nlen] = '\0';
  1211. X        converting(info.name, (int)info.nlen, info.type, info.auth);
  1212. X        print_bin_hdr("Reading", &info);
  1213. X
  1214. X        /* ensure the output files have no bogus UNIX characters */
  1215. X        unixify(base_fname);
  1216. X        mode_to_fname_suffix(mode, base_fname,
  1217. X            data_fname, &data_suffix, rsrc_fname, &rsrc_suffix);
  1218. X
  1219. X        /* always use suffix on write */
  1220. X
  1221. X        if (*data_fname) {
  1222. X            len = strlen(data_fname) + strlen(data_suffix);
  1223. X            if (len >= sizeof(data_fname))
  1224. X                error("Error: generated data_fname would be too long", "");
  1225. X            strcat(data_fname, data_suffix);
  1226. X            data_file = mopen(data_fname, "", "w");
  1227. X        }
  1228. X
  1229. X        if (*rsrc_fname) {
  1230. X            len = strlen(rsrc_fname) + strlen(rsrc_suffix);
  1231. X            if (len >= sizeof(rsrc_fname))
  1232. X                error("Error: generated rsrc_fname would be too long", "");
  1233. X            strcat(rsrc_fname, rsrc_suffix);
  1234. X            rsrc_file = mopen(rsrc_fname, "", "w");
  1235. X        }
  1236. X
  1237. X        /* process the data fork */
  1238. X        bcopy((char*)info.dlen, (char *) &temp, 4);
  1239. X        nchars = temp;
  1240. X        extra_chars = 127 - (nchars + 127) % 128;
  1241. X
  1242. X        if (*data_fname) {
  1243. X
  1244. X            if (translate_eol)
  1245. X                while (nchars--) {
  1246. X                    (b = getc(binfile)) == EOF &&
  1247. X                        error("Error: getc failed on binfile", "");
  1248. X                    if (b == CR)
  1249. X                        b = LF;
  1250. X                    putc((char)b, data_file) == EOF &&
  1251. X                        error("Error: putc failed on data_file", "");
  1252. X                }
  1253. X
  1254. X            else
  1255. X                while (nchars--) {
  1256. X                    (b = getc(binfile)) == EOF &&
  1257. X                        error("Error: getc failed on binfile", "");
  1258. X                    putc((char)b, data_file) == EOF &&
  1259. X                        error("Error: putc failed on data_file", "");
  1260. X                }
  1261. X        
  1262. X            mclose(&data_file, data_fname);
  1263. X
  1264. X        } else {
  1265. X
  1266. X            /* skip the actual data */
  1267. X            while (nchars--) {
  1268. X                getc(binfile) == EOF &&
  1269. X                    error("Error: getc failed on binfile", "");
  1270. X            }
  1271. X        }
  1272. X
  1273. X        /* eat the padding to 128 byte boundary */
  1274. X        while (extra_chars--) {
  1275. X            getc(binfile) == EOF &&
  1276. X                error("Error: getc failed on binfile", "");
  1277. X        }
  1278. X
  1279. X        /* process the rsrc fork */
  1280. X
  1281. X        bcopy((char*)info.rlen, (char *) &temp, 4);
  1282. X        nchars = temp;
  1283. X
  1284. X        if (*rsrc_fname) {
  1285. X            while (nchars--) {
  1286. X                (b = getc(binfile)) == EOF &&
  1287. X                    error("Error: getc failed on binfile", "");
  1288. X                putc((char)b, rsrc_file) == EOF &&
  1289. X                    error("Error: putc failed on rsrc_file", "");
  1290. X            }
  1291. X            mclose(&rsrc_file, rsrc_fname);
  1292. X        }
  1293. X
  1294. X        mclose(&binfile, "binfile");
  1295. X    }
  1296. }
  1297. X
  1298. usage()
  1299. {
  1300. X    fprintf(stderr, Usage, cmdname, VERSION/100.);
  1301. X    exit(1);
  1302. X    /*NOTREACHED*/
  1303. }
  1304. X
  1305. X
  1306. /* My FileIO routines, to enable clean implementation of info_only */
  1307. /* If info_only and open for write, inform user and use devnull instead */
  1308. /* If pipe_out and open for write, inform user and use stdout instead */
  1309. /* If trying to close devnull or stdout, don't */
  1310. X
  1311. FILE *
  1312. mopen(name, exten, type)
  1313. X    char *name;
  1314. X    char *exten;
  1315. X    char *type;
  1316. {
  1317. X    FILE *result;
  1318. X
  1319. X    switch (*type) {
  1320. X    case 'r':
  1321. X        result = fopen(name, type);
  1322. X        if (result == NULL && *exten) {
  1323. X            /* see if adding the extension would help */
  1324. X            int len_root = strlen(name);
  1325. X            int len_ext = strlen(exten);
  1326. X            char *dotspot = name + len_root - len_ext;
  1327. X            if (strcmp(exten, dotspot)) {
  1328. X                if (len_root + len_ext >= SYSNAMELEN)
  1329. X                    error("Error: generated file name would be too long", "");
  1330. X                strcat(name, exten);
  1331. X                result = fopen(name, type);
  1332. X            }
  1333. X        }
  1334. X        if (result == NULL)
  1335. X            error("Cannot open %s for read", name);
  1336. X        else {
  1337. X            fprintf(verbose, "\n%-15s%-27s\n",
  1338. X                "Input file", name);
  1339. X            fflush(verbose);
  1340. X        }
  1341. X        break;
  1342. X
  1343. X    case 'w':
  1344. X        if (info_only) {
  1345. X            fprintf(verbose, " %-14s%-27s -I (info only) specified\n",
  1346. X                " No output to", name);
  1347. X            fflush(verbose);
  1348. X            result = devnull;
  1349. X        } else if (pipe_out) {
  1350. X            fprintf(verbose, " %-14s%-27s -P (pipe to stdout) specified\n",
  1351. X                " stdout, vice", name);
  1352. X            fflush(verbose);
  1353. X            result = stdout;
  1354. X        } else {
  1355. X            result = fopen(name, type);
  1356. X            if (result == NULL)
  1357. X                error("Cannot open %s for write", name);
  1358. X            else {
  1359. X                fprintf(verbose, "%-15s%-27s\n",
  1360. X                    "Output file", name);
  1361. X                fflush(verbose);
  1362. X            }
  1363. X        }
  1364. X        break;
  1365. X
  1366. X    default:
  1367. X        fprintf(stderr, "%s: internal error in mopen -- exiting\n", cmdname);
  1368. X        exit(2);
  1369. X
  1370. X    }
  1371. X
  1372. X    return result;
  1373. }
  1374. X
  1375. mclose(stream_p, name)
  1376. X    FILE **stream_p;
  1377. X    char *name;
  1378. {
  1379. X    if (*stream_p && *stream_p != devnull && *stream_p != stdout) {
  1380. X        if (fclose(*stream_p) == EOF)
  1381. X            error("Error closing %s", name);
  1382. X    }
  1383. X
  1384. X    *stream_p = (FILE *)0;
  1385. }
  1386. X
  1387. converting(name, len, type, auth)
  1388. X    byte *name;
  1389. X    int len;
  1390. X    byte *type;
  1391. X    byte *auth;
  1392. {
  1393. X    char buffer[SYSNAMELEN];
  1394. X
  1395. X    /* make a copy to ensure null terminated */
  1396. X    strncpy(buffer, (char*)name, len);
  1397. X    buffer[len] = 0;
  1398. X
  1399. X    fprintf(convert,
  1400. X        "%-15s%-30s type = \"%4.4s\", author = \"%4.4s\"\n",
  1401. X         info_only ? "Inspecting" : "Converting",
  1402. X         buffer, type, auth);
  1403. X    fflush(convert);
  1404. }
  1405. X
  1406. print_bin_hdr(msg, hdr)
  1407. X    char *msg;
  1408. X    info_header *hdr;
  1409. {
  1410. X    ulong otime, xtime;
  1411. X    long    dlen, rlen;
  1412. X    bcopy((char*)hdr->ctim, (char*)&otime, 4);
  1413. X    DEBUG && fprintf(debug,
  1414. X        "DEBUG: verifying mac2unix/unix2mac: 0x%8lx, 0x%8lx\n",
  1415. X        otime, unix2mac(mac2unix(otime)));
  1416. X
  1417. X    bcopy((char*)hdr->dlen, (char*)&dlen, 4);
  1418. X    bcopy((char*)hdr->rlen, (char*)&rlen, 4);
  1419. X
  1420. X    DEBUG && fprintf(debug, "\
  1421. %s\n\
  1422. \tName     %.*s\n\
  1423. \tType     %.4s\n\
  1424. \tCreator  %.4s\n\
  1425. \tDataLen  %ld\n\
  1426. \tRsrcLen  %ld\n\
  1427. ",
  1428. X        msg,
  1429. X        hdr->nlen, hdr->name,
  1430. X        hdr->type,
  1431. X        hdr->auth,
  1432. X        mac2long(dlen),
  1433. X        mac2long(rlen),
  1434. X        0);
  1435. X
  1436. X    bcopy((char*)hdr->ctim, (char*)&otime, 4);
  1437. X    xtime = mac2unix(otime);
  1438. X    DEBUG && fprintf(debug, "raw ctim: 0x%8lx, mac2unix: 0x%8lx\n",
  1439. X        otime, xtime);
  1440. X    DEBUG && fflush(debug);
  1441. X
  1442. X    fprintf(verbose, "\tCreated  %s", ctime((time_t *)&xtime));
  1443. X    fflush(verbose);
  1444. X
  1445. X    bcopy((char*)hdr->mtim, (char*)&otime, 4);
  1446. X    xtime = mac2unix(otime);
  1447. X    DEBUG && fprintf(debug, "raw mtim: 0x%8lx, mac2unix: 0x%8lx\n",
  1448. X        otime, xtime);
  1449. X    DEBUG && fflush(debug);
  1450. X    fprintf(verbose, "\tModified %s", ctime((time_t *)&xtime));
  1451. X    fflush(verbose);
  1452. X
  1453. }
  1454. SHAR_EOF
  1455. chmod 0444 mcvert.c ||
  1456. echo 'restore of mcvert.c failed'
  1457. Wc_c="`wc -c < 'mcvert.c'`"
  1458. test 44551 -eq "$Wc_c" ||
  1459.     echo 'mcvert.c: original size 44551, current size' "$Wc_c"
  1460. fi
  1461. # ============= hqxify.c ==============
  1462. if test -f 'hqxify.c' -a X"$1" != X"-c"; then
  1463.     echo 'x - skipping hqxify.c (File already exists)'
  1464. else
  1465. echo 'x - extracting hqxify.c (Text)'
  1466. sed 's/^X//' << 'SHAR_EOF' > 'hqxify.c' &&
  1467. #include "mactypes.h"
  1468. X
  1469. /* HQXBUFLEN must be large enough to hold a complete hqx header */
  1470. #define HQXBUFLEN 512
  1471. byte hqxbuf[HQXBUFLEN + 1], *buf_ptr, *buf_end, *buf_start = hqxbuf + 1;
  1472. X
  1473. /* Note: line[0] stores the run length character,
  1474. X * so line is one greater than MAXLINE  */
  1475. #define MAXLINE 2048
  1476. byte line[MAXLINE + 1], *line_ptr, *line_end, *line_start = line + 1;
  1477. X
  1478. /* keep the compiler happy */
  1479. #define LINE_START ((char*)(line_start))
  1480. X
  1481. extern char *cmdname;
  1482. X
  1483. int line_count, file_count;
  1484. int save_state, total_bytes, save_run_length;
  1485. word save_accum;
  1486. char binfname[SYSNAMELEN], hqxfname[SYSNAMELEN];
  1487. FILE *hqxfile, *binfile;
  1488. X
  1489. X
  1490. /*
  1491. X * hqxsuspect caches whether or not we have gotten past all suspect data
  1492. X * at the head of a file, for example, a mail header.  hqxsuspect is set
  1493. X * on every new hqx file read, and reset only in non_suspect()
  1494. X */
  1495. int hqxsuspect;
  1496. extern suspect_shorter;
  1497. extern suspect_same;
  1498. X
  1499. extern int info_only;
  1500. X
  1501. /* This routine reads the header of a hqxed file and appropriately twiddles it,
  1502. X    determines if it has CRC problems, creates the .bin file, and puts the info
  1503. X    into the .bin file.
  1504. X    Output is hqx_datalen, hqx_rsrclen, type, binfname, binfile.
  1505. X     Returns 0 iff failed to read header.
  1506. X */
  1507. X
  1508. X
  1509. int
  1510. hqx_to_bin_hdr(type, hqx_datalen, hqx_rsrclen, same_file_only)
  1511. X    char *type;
  1512. X    ulong *hqx_datalen, *hqx_rsrclen;
  1513. X    int same_file_only;
  1514. {
  1515. X    register byte *hqx_ptr, *hqx_end;
  1516. X    register ulong calc_crc;
  1517. X    hqx_buf *hqx_block;
  1518. X    hqx_header *hqx;
  1519. X    info_header info;
  1520. X    ulong mtim;
  1521. X    short crc;
  1522. X    long len;
  1523. X
  1524. X    extern word magic[];
  1525. X    extern char *dir, *ext;
  1526. X    extern short calc_mb_crc();
  1527. X
  1528. X    /* read the hqx header, 
  1529. X     * assuming that I won't exhaust hqxbuf in so doing --
  1530. X     * that is, that hqxbuf is always large enough (it is)
  1531. X     */
  1532. X    (void)fill_hqxbuf(same_file_only);
  1533. X    /*
  1534. X     * If we are reading multiple files, then we could have the last
  1535. X     * unread line of the "previous" file be just a colon (since we are
  1536. X     * length driven, and stopped when we processed the expected
  1537. X     * lengths), and the prior fill_hqxbuf() call would find it and
  1538. X     * return 0, leaving the buffer unfilled.  So, if we have zero
  1539. X     * bytes so far, just fill it again.
  1540. X     */
  1541. X    if (total_bytes == 0) {
  1542. X        DEBUG && fprintf(debug,
  1543. X            "%s: Note: had to call fill_hqxbuf again in hqx_to_bin_hdr\n",
  1544. X            cmdname);
  1545. X        DEBUG && fflush(debug);
  1546. X        (void)fill_hqxbuf(same_file_only);
  1547. X    }
  1548. X    if (same_file_only == 1 && total_bytes == 0)
  1549. X        return 0;
  1550. X    if (total_bytes < MIN_HQX_HDR) {
  1551. X        fprintf(verbose, "%s: %s (%d < %d): bad file format? -- exiting\n",
  1552. X            cmdname, "error: hqx_header too short", total_bytes, MIN_HQX_HDR);
  1553. X        fflush(verbose);
  1554. X        exit(2);
  1555. X    }
  1556. X
  1557. X    hqx_block = (hqx_buf *) buf_ptr;
  1558. X    hqx = (hqx_header *) (hqx_block->name + hqx_block->nlen);
  1559. X    hqx_ptr = buf_ptr;
  1560. X    hqx_end = (byte *) hqx + sizeof(hqx_header) - 1;
  1561. X    calc_crc = 0;
  1562. X    while (hqx_ptr < hqx_end)
  1563. X        calc_crc = (((calc_crc & 0xff) << 8) | *hqx_ptr++) ^ magic[calc_crc >> 8];
  1564. X    calc_crc = ((calc_crc & 0xff) << 8) ^ magic[calc_crc >> 8];
  1565. X    calc_crc = ((calc_crc & 0xff) << 8) ^ magic[calc_crc >> 8];
  1566. X    buf_ptr = hqx_ptr;
  1567. X
  1568. X    /* stuff the hqx header data into the info header */
  1569. X    bzero((char*)&info, sizeof(info_header));
  1570. X    info.nlen = hqx_block->nlen;
  1571. X    if (info.nlen > sizeof(info.name))
  1572. X        error("Error: corrupt BinHex data format", "");
  1573. X    strncpy((char*)info.name, (char*)hqx_block->name, (int)info.nlen);/* name */
  1574. X
  1575. X    /* now make sure the resulting name is valid for length only */
  1576. X    info.nlen = macify((char*)info.name, (int)info.nlen, 0);
  1577. X
  1578. X    bcopy((char*)hqx->type, (char*)info.type, 9);       /* type, author, flag */
  1579. X    info.flags &= 0x7e;               /* reset lock bit, init bit */
  1580. X    if (hqx->protect & 0x40)
  1581. X        info.protect = 1;           /* copy protect bit */
  1582. X    bcopy((char*)hqx->dlen, (char*)info.dlen, 8);           /* dlen, rlen */
  1583. X    mtim = unix2mac((ulong)time((long*)0));
  1584. X    bcopy((char*)&mtim, (char*)info.mtim, 4);
  1585. X    bcopy((char*)&mtim, (char*)info.ctim, 4);
  1586. X    info.uploadvers = '\201';
  1587. X    info.readvers = '\201';
  1588. X
  1589. X    /* calculate MacBinary CRC */
  1590. X    crc = calc_mb_crc((unsigned char*)&info, 124L, 0);
  1591. X    info.crc[0] = (char) (crc >> 8);
  1592. X    info.crc[1] = (char) crc;
  1593. X
  1594. X    /* Create the .bin file and write the info to it */
  1595. X
  1596. X    unixify((char*)hqx_block->name);
  1597. X    converting(info.name, (int)info.nlen, info.type, info.auth);
  1598. X    print_bin_hdr("Creating", &info);
  1599. X
  1600. X    len = strlen(dir) + strlen((char*)hqx_block->name) + strlen(ext) + 1;
  1601. X    if (len >= sizeof(binfname))
  1602. X        error("Error: generated binfname would be too long", "");
  1603. X    sprintf(binfname, "%s/%s%s", dir, hqx_block->name, ext);
  1604. X    binfile = mopen(binfname, "", "w");
  1605. X
  1606. X    check_hqx_crc((word)calc_crc, "File header CRC mismatch in %s", binfname);
  1607. X    if (1 != fwrite((char*)&info, sizeof(info), 1, binfile))
  1608. X        error("fwrite failed on binfile", "");
  1609. X
  1610. X    /* Get a couple of items we'll need later */
  1611. X    bcopy((char*)info.dlen, (char*)hqx_datalen, 4);
  1612. X    *hqx_datalen = mac2long(*hqx_datalen);
  1613. X    bcopy((char*)info.rlen, (char*)hqx_rsrclen, 4);
  1614. X    *hqx_rsrclen = mac2long(*hqx_rsrclen);
  1615. X    bcopy((char*)info.type, (char*)type, 4);
  1616. X
  1617. X    /* emit useful debugging info */
  1618. X    DEBUG && fprintf(debug, "\tdata_len=%10ld\t\trsrc_len=%10ld\n",
  1619. X        *hqx_datalen, *hqx_rsrclen);
  1620. X    DEBUG && fflush(debug);
  1621. X
  1622. X    return 1;
  1623. }
  1624. X
  1625. /* This routine reads the header of a bin file and appropriately twiddles it,
  1626. X    creates the .hqx file, and puts the info into the .hqx file.
  1627. X    Output is hqx_datalen, hqx_rsrclen, type, hqxfname, hqxfile */
  1628. X
  1629. bin_to_hqx_hdr(hqx_datalen, hqx_rsrclen)
  1630. X    ulong *hqx_datalen, *hqx_rsrclen;
  1631. {
  1632. X    register byte *hqx_ptr, *hqx_end;
  1633. X    register ulong calc_crc;
  1634. X    hqx_buf *hqx_block;
  1635. X    hqx_header *hqx;
  1636. X    info_header info;
  1637. X    extern word magic[];
  1638. X    extern char **hqxnames_left;
  1639. X    extern char *ext;
  1640. X    long len;
  1641. X
  1642. X    len = strlen(*hqxnames_left);
  1643. X    if (len >= sizeof(binfname))
  1644. X        error("Error: specified binfname is too long", "");
  1645. X    strcpy(binfname, *hqxnames_left++);
  1646. X    binfile = mopen(binfname, ext, "r");
  1647. X
  1648. X    if (!fread((char*)&info, sizeof(info), 1, binfile))
  1649. X        error("Unexpected EOF in MacBinary header of %s", binfname);
  1650. X
  1651. X    /* stuff the info header into the hqx header */
  1652. X    hqx_block = (hqx_buf *) buf_ptr;
  1653. X    hqx_block->nlen = info.nlen;
  1654. X    if (info.nlen > sizeof(hqx_block->name))
  1655. X        error("Error: corrupt MacBinary data format", "");
  1656. X    strncpy((char*)hqx_block->name, (char*)info.name, (int)info.nlen);
  1657. X    /*
  1658. X     * We expect a valid Macintosh file name since it came from a MacBinary file
  1659. X     * so we don't potentially corrupt a valid copied name via macify translate.
  1660. X     * File name length should not be a problem, so we do nothing.
  1661. X     */
  1662. X    hqx = (hqx_header *) (hqx_block->name + hqx_block->nlen);
  1663. X    hqx->version = 0;
  1664. X    bcopy((char*)info.type, (char*)hqx->type, 9);   /* type, author, flags */
  1665. X    hqx->flags &= 0x7e;               /* reset lock bit, init bit */
  1666. X    if (info.protect == 1)
  1667. X        hqx->protect = 0;           /* protect bit: 0x40 */
  1668. X    else
  1669. X        hqx->protect = 0;
  1670. X    bcopy((char*)info.dlen, (char*)hqx->dlen, 8);           /* dlen, rlen */
  1671. X
  1672. X    /* Create the .hqx file and write the info to it */
  1673. X
  1674. #ifdef notdef
  1675. X       This is the right thing to check but the Sun optimizing
  1676. X       compiler gives a (valid) warning that info.nlen (one char,
  1677. X       255 max) is always less than sizeofhqxfname) which is
  1678. X       hardwired to 1024 since version 1.99.  Since we have already
  1679. X       checked info.nlen above, we skip the test and avoid the warning.
  1680. X
  1681. X    if (info.nlen >= sizeof(hqxfname))
  1682. X        error("Error: generated hqxfname would be too long", "");
  1683. #endif
  1684. X
  1685. X    strncpy(hqxfname, (char*)info.name, (int)info.nlen);
  1686. X    hqxfname[info.nlen] = '\0';
  1687. X    unixify(hqxfname);
  1688. X    converting(info.name, (int)info.nlen, info.type, info.auth);
  1689. X    print_bin_hdr("Reading", &info);
  1690. X
  1691. X    calc_crc = 0;
  1692. X    hqx_ptr = (byte *) hqx_block;
  1693. X    hqx_end = hqx_ptr + hqx_block->nlen + sizeof(hqx_header);
  1694. X    while (hqx_ptr < hqx_end)
  1695. X        calc_crc = (((calc_crc & 0xff) << 8) | *hqx_ptr++) ^ magic[calc_crc >> 8];
  1696. X    calc_crc = ((calc_crc & 0xff) << 8) ^ magic[calc_crc >> 8];
  1697. X    calc_crc = ((calc_crc & 0xff) << 8) ^ magic[calc_crc >> 8];
  1698. X    buf_ptr = hqx_end;
  1699. X    write_hqx_crc((word)calc_crc);
  1700. X
  1701. X    /* Get a couple of items we'll need later */
  1702. X    bcopy((char*)info.dlen, (char*)hqx_datalen, 4);
  1703. X    *hqx_datalen = mac2long(*hqx_datalen);
  1704. X    bcopy((char*)info.rlen, (char*)hqx_rsrclen, 4);
  1705. X    *hqx_rsrclen = mac2long(*hqx_rsrclen);
  1706. }
  1707. X
  1708. X
  1709. /* This routine copies bytes from the decoded input stream to the output.  
  1710. X    It also pads to a multiple of 128 bytes on the output, which is part
  1711. X    of the .bin format */
  1712. word
  1713. hqx_to_bin_fork(nbytes)
  1714. X    register ulong nbytes;
  1715. {
  1716. X    register byte *cp;
  1717. X    register ulong calc_crc;
  1718. X    register int c_length;
  1719. X    ulong extra_bytes;
  1720. X    extern word magic[];
  1721. X    long avail = 0;    /* used for internal consistency checking */
  1722. X    int wrote;
  1723. X
  1724. X    extra_bytes = 127 - (nbytes + 127) % 128;    /* pad fork to mult of
  1725. X                             * 128 bytes */
  1726. X    calc_crc = 0;
  1727. X    for (;;) {
  1728. X        cp = buf_ptr;
  1729. X        c_length = (cp + nbytes > buf_end) ? buf_end - cp : nbytes;
  1730. X        /* we can only check readily if we read it here */
  1731. X        if (avail && c_length > avail)
  1732. X            error("hqx_to_bin_fork: writing %ld too many bytes",
  1733. X                (char*)c_length - avail);
  1734. X        nbytes -= c_length;
  1735. X        wrote = fwrite((char*)cp, sizeof(byte), c_length, binfile);
  1736. X        if (wrote != c_length)
  1737. X            error("hqx_to_bin_fork: fwrite on binfile wrote %ld bytes too few",
  1738. X                (char*)c_length-wrote);
  1739. X        while (c_length--)
  1740. X            calc_crc = (((calc_crc & 0xff) << 8) | *cp++) ^ magic[calc_crc >> 8];
  1741. X        if (!nbytes)
  1742. X            break;
  1743. X        avail = fill_hqxbuf(0);
  1744. X    }
  1745. X    buf_ptr = cp;
  1746. X    while (extra_bytes--)
  1747. X        if (EOF == putc(0, binfile))
  1748. X            error("Error: putc failed on binfile", "");
  1749. X    calc_crc = ((calc_crc & 0xff) << 8) ^ magic[calc_crc >> 8];
  1750. X    calc_crc = ((calc_crc & 0xff) << 8) ^ magic[calc_crc >> 8];
  1751. X    return (word) calc_crc;
  1752. }
  1753. X
  1754. /* This routine copies bytes from the input stream to the encoded output.  
  1755. X    It also pads to a multiple of 128 bytes on the input, which is part
  1756. X    of the .bin format */
  1757. word
  1758. bin_to_hqx_fork(nbytes)
  1759. X    register ulong nbytes;
  1760. {
  1761. X    register byte *cp;
  1762. X    register ulong calc_crc;
  1763. X    register int c_length;
  1764. X    ulong extra_bytes;
  1765. X    extern word magic[];
  1766. X
  1767. X    extra_bytes = 127 - (nbytes + 127) % 128;    /* pad fork to mult of
  1768. X                             * 128 bytes */
  1769. X    calc_crc = 0;
  1770. X    for (;;) {
  1771. X        cp = buf_ptr;
  1772. X        c_length = (cp + nbytes > buf_end) ? buf_end - cp : nbytes;
  1773. X        nbytes -= c_length;
  1774. X        if (c_length != fread((char*)cp, sizeof(byte), c_length, binfile))
  1775. X            error("fread failed on binfile", "");
  1776. X        buf_ptr += c_length;
  1777. X        while (c_length--)
  1778. X            calc_crc = (((calc_crc & 0xff) << 8) | *cp++) ^ magic[calc_crc >> 8];
  1779. X        if (!nbytes)
  1780. X            break;
  1781. X        empty_hqxbuf();
  1782. X    }
  1783. X    buf_ptr = cp;
  1784. X
  1785. X    fseek(binfile, (long)extra_bytes, 1);
  1786. X    calc_crc = ((calc_crc & 0xff) << 8) ^ magic[calc_crc >> 8];
  1787. X    calc_crc = ((calc_crc & 0xff) << 8) ^ magic[calc_crc >> 8];
  1788. X    return (word) calc_crc;
  1789. }
  1790. X
  1791. /* Essentials for Binhex 8to6 run length encoding */
  1792. #define RUNCHAR 0x90
  1793. #define MAXRUN 255
  1794. #define IS_LEGAL <0x40
  1795. #define ISNT_LEGAL >0x3f
  1796. #define DONE 0x7F        /* tr68[':'] = DONE, since Binhex terminator is ':' */
  1797. #define SKIP 0x7E        /* tr68['\n'|'\r'] = SKIP, i. e. end of line char.  */
  1798. X    /* We also treat '\0' as SKIP to handle files without trailing newline */
  1799. X
  1800. X    /*
  1801. X       NOTE: we really don't do a very good job of handling lines
  1802. X       with ^M's as the end of line character, since we jettison
  1803. X       the entire UNIX line (which can look like multiple Mac
  1804. X       lines) when rejecting the line.  Easiest way to fix this is
  1805. X       to write our own version of fgets which breaks on ^M or ^J.
  1806. X     */
  1807. X
  1808. #define FAIL 0x7D        /* character illegal in binhex file */
  1809. X
  1810. byte tr86[] =
  1811. "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr";
  1812. byte tr68[] = {
  1813. /* 0x00 */
  1814. X    SKIP, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  1815. X    FAIL, FAIL, SKIP, FAIL, FAIL, SKIP, FAIL, FAIL,
  1816. /* 0x10 */
  1817. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  1818. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  1819. /* 0x20 */
  1820. X    FAIL, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
  1821. X    0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, FAIL, FAIL,
  1822. /* 0x30 */
  1823. X    0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, FAIL,
  1824. X    0x14, 0x15, DONE, FAIL, FAIL, FAIL, FAIL, FAIL,
  1825. /* 0x40 */
  1826. X    0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
  1827. X    0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, FAIL,
  1828. /* 0x50 */
  1829. X    0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, FAIL,
  1830. X    0x2C, 0x2D, 0x2E, 0x2F, FAIL, FAIL, FAIL, FAIL,
  1831. /* 0x60 */
  1832. X    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, FAIL,
  1833. X    0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, FAIL, FAIL,
  1834. /* 0x70 */
  1835. X    0x3D, 0x3E, 0x3F, FAIL, FAIL, FAIL, FAIL, FAIL,
  1836. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  1837. /* 0x80 */
  1838. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  1839. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  1840. /* 0x90 */
  1841. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  1842. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  1843. /* 0xA0 */
  1844. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  1845. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  1846. /* 0xB0 */
  1847. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  1848. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  1849. /* 0xC0 */
  1850. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  1851. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  1852. /* 0xD0 */
  1853. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  1854. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  1855. /* 0xE0 */
  1856. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  1857. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  1858. /* 0xF0 */
  1859. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  1860. X    FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
  1861. };
  1862. X
  1863. /*
  1864. X *  This procedure transparently reads and decodes the hqx input.
  1865. X *  It does run length and 6 to 8 decoding.
  1866. X *  As many lines as required are read to fill up buf.
  1867. X * Global Input
  1868. X *  buf_start
  1869. X *  line_ptr
  1870. X *  save_*
  1871. X * Global Output
  1872. X *  buf_ptr end of buffer used
  1873. X *  line_ptr
  1874. X *  save_*
  1875. X * Internal
  1876. X *  line     holds the encoded incoming ascii line.
  1877. X *  buf      holds the decoding binary binary. [what the heck does this mean?]
  1878. X *  buf[-1]  holds the character to be repeated for run length encoding.
  1879. X */
  1880. #define READING 0
  1881. #define SKIPPING 1
  1882. #define FIND_START_COLON 2
  1883. #define FINDING_COLON 3
  1884. X
  1885. /*
  1886. X
  1887. X * It's too bad we can't look for ``(This file ..'' when hunting for a
  1888. X * starting colon, but we don't emit such a line at the head of every
  1889. X * segment, so we can't expect to find one, now, can we?
  1890. X
  1891. X * We were really too brittle when scanning, since we only
  1892. X * accepted lines which were exactly 64 (HQXLINELEN) characters long.
  1893. X * Fixed in version 1.83.  But allowing any length valid line
  1894. X * permitted the false-match-in-mail-headers-problem for lines like "---".
  1895. X * Better header skipping provided in 1.84.
  1896. X
  1897. X * XXX: rather than decode line inplace, it would be better
  1898. X * to leave the original intact to enable better warning messages
  1899. X
  1900. X */
  1901. X
  1902. /* returns the number of bytes read */
  1903. fill_hqxbuf(same_file_only)
  1904. X    int same_file_only;
  1905. {
  1906. X    register ulong c, accum;
  1907. X    register int not_in_a_run = TRUE, state68;
  1908. X    register byte *fast_buf, *fast_line;
  1909. X    static int phase = FIND_START_COLON;
  1910. X    long avail;
  1911. X
  1912. X    buf_ptr = fast_buf = buf_start;
  1913. X    fast_line = line_ptr;
  1914. X    state68 = save_state;
  1915. X    accum = save_accum;
  1916. X    if (save_run_length > 0) {
  1917. X        c = save_run_length;
  1918. X        save_run_length = 0;
  1919. X        goto continue_run;
  1920. X    }
  1921. X
  1922. X    while (fast_buf < buf_end) {
  1923. X
  1924. next_char:
  1925. X        if ((c = *fast_line++) ISNT_LEGAL) {
  1926. X            if (c == DONE) {
  1927. X                /* done processing the file, so get out */
  1928. X                /* phase has already been set by read processing */
  1929. X                break;
  1930. X          }
  1931. X
  1932. X    next_line:
  1933. X            if (!fgets(LINE_START, MAXLINE, hqxfile)) {
  1934. X                if (same_file_only) {
  1935. X                    avail = fast_buf - buf_ptr;
  1936. X                    if (avail != 0) {
  1937. X                        DEBUG && fprintf(debug, "DEBUG: avail: %d\n", avail);
  1938. X                        DEBUG && fflush(debug);
  1939. X                        error(
  1940. X                "Premature EOF reading non-initial BinHex 4.0 header from %s",
  1941. X                            hqxfname);
  1942. X                    } else {
  1943. X                        /* this routine may be called many times in a row,
  1944. X                         * and we must ensure that we don't allow fast_line
  1945. X                         * to march beyond the end of line (it did), so we jam
  1946. X                         * fast_line to the start of the line, and salt the
  1947. X                         * line to mark it invalid, so a new line will be fetched.
  1948. X                         * Jeepers, how I hate the (il)logic of this routine!
  1949. X                         */
  1950. X                        fast_line = line_start;
  1951. X                        *fast_line = SKIP;
  1952. X                        break;
  1953. X                    }
  1954. X                    /*NOTREACHED*/
  1955. X                } else if (new_in_hqx_file() == 0) {
  1956. X                    /*
  1957. X                     * Used to assume if no more input available through error or
  1958. X                     * exhaustion while looking for valid data then must be done.
  1959. X                     * But we are demand driven (now) and if called, must
  1960. X                     * find data.  So we don't silently exit any more.
  1961. X                     */
  1962. X                    error("Premature EOF while reading BinHex 4.0 %s", hqxfname);
  1963. X                }
  1964. X            }
  1965. X            line_ptr = line_start;
  1966. X
  1967. X            if (Debug > 1) {
  1968. X                      fprintf(debug, "DEBUG: input: %s", line_start);
  1969. X                      fflush(debug);
  1970. X             }
  1971. X
  1972. X    scan_line:
  1973. X
  1974. X            /* ensure the the entire line is valid */
  1975. X
  1976. X            fast_line = line_ptr;
  1977. X            while ((*fast_line = tr68[*fast_line]) IS_LEGAL)
  1978. X                fast_line++;
  1979. X
  1980. X            /* grab the stopper */
  1981. X            c = *fast_line;
  1982. X
  1983. X            /* check for validity, transition phases as required */
  1984. X            switch (phase) {
  1985. X
  1986. X            case READING:
  1987. X            case SKIPPING:
  1988. X            case FINDING_COLON:
  1989. X                if (SKIP == c && fast_line > line_ptr &&
  1990. X                    ( 0 == hqxsuspect ||
  1991. X                        non_suspect((char *)line_ptr, (char *)fast_line) )
  1992. X                ) {
  1993. X                    /* the entire line is valid (again), so (resume) reading */
  1994. X                    /* hack: require the line to be non-empty to simplify logic */
  1995. X                    /* require line to non suspect [outside [mail] header] */
  1996. X                    phase = READING;
  1997. X                    break;
  1998. X                }
  1999. X                if (c == DONE && tr68[fast_line[1]] == SKIP) {
  2000. X                    /*
  2001. X                     * valid encoded last line, so
  2002. X                     * set phase for next line, and process this line --
  2003. X                     * we exit the fill-the-buffer loop when the terminal
  2004. X                     * colon is encountered during line processing
  2005. X                     */
  2006. X                    phase = FIND_START_COLON;
  2007. X                    break;
  2008. X                }
  2009. X
  2010. X                /* line is not entirely valid, so do some flavor of skipping */
  2011. X                phase = (phase == FINDING_COLON) ? FIND_START_COLON : SKIPPING;
  2012. X                /* we're suspicious again, since we could be reading a
  2013. X                 * concatenated multi-segmented file */
  2014. X                hqxsuspect = 1;
  2015. X                goto next_line;
  2016. X
  2017. X            case FIND_START_COLON:
  2018. X                if (*line_start == DONE) {
  2019. X                    /* can't transition to READING
  2020. X                     * until know that entire line is valid
  2021. X                     * so transition to intermediate state
  2022. X                     */
  2023. X                    phase = FINDING_COLON;
  2024. X                    /* skip the initial colon */
  2025. X                    line_ptr++;
  2026. X                    goto scan_line;
  2027. X                }
  2028. X                goto next_line;
  2029. X
  2030. X            }
  2031. X
  2032. X            /* we've read in a valid line, so start processing it */
  2033. X            fast_line = line_ptr;
  2034. X            c = *fast_line++;
  2035. X
  2036. X            /*
  2037. X             * Jskud 15Jul92: fix bug reported by Info-Mac Moderator Bill
  2038. X             * regarding case of last line just :
  2039. X             * The line is valid, but it has no data, so don't ingest it.
  2040. X             */
  2041. X
  2042. X            if (c == DONE)
  2043. X                break;
  2044. X
  2045. X            if (Debug > 1) {
  2046. X                fprintf(debug, "DEBUG: processing above line\n\n");
  2047. X                fflush(debug);
  2048. X            }
  2049. X
  2050. X        }
  2051. X
  2052. X        /* Finally, we have the next 6 bits worth of data in "c" as input. */
  2053. X        /* Note: we use "c" as the output of this processing too */
  2054. X        switch (state68++) {
  2055. X        case 0:
  2056. X            accum = c;
  2057. X            goto next_char;
  2058. X        case 1:
  2059. X            accum = (accum << 6) | c;
  2060. X            c = accum >> 4;
  2061. X            break;
  2062. X        case 2:
  2063. X            accum = (accum << 6) | c;
  2064. X            c = (accum >> 2) & 0xff;
  2065. X            break;
  2066. X        case 3:
  2067. X            /* we avoid any miniscule optimizations here
  2068. X             * to maintain parallelism and clarity
  2069. X             * which should enhance program maintainability
  2070. X             */
  2071. X            accum = (accum << 6) | c;
  2072. X            c = accum & 0xff;
  2073. X            state68 = 0;
  2074. X            break;
  2075. X        }
  2076. X        if (not_in_a_run)
  2077. X            if (c != RUNCHAR)
  2078. X                *fast_buf++ = c;
  2079. X            else {
  2080. X                not_in_a_run = FALSE;
  2081. X                goto next_char;
  2082. X            }
  2083. X        else {
  2084. X            /* "c" has the run total length, not just the incremental,
  2085. X               hence the post decrement is correct */
  2086. X            if (c--) {
  2087. X                avail = buf_end - fast_buf;
  2088. X                if (c > avail) {
  2089. X                    save_run_length = c - avail;
  2090. X                    c = avail;
  2091. X                }
  2092. X        continue_run:
  2093. X                {
  2094. X                    register char ch = fast_buf[-1];
  2095. X
  2096. X                    while (c--)
  2097. X                        *fast_buf++ = ch;
  2098. X                }
  2099. X
  2100. X            } else
  2101. X                /* handle special case of 0x9000 => 0x90 */
  2102. X                *fast_buf++ = RUNCHAR;
  2103. X
  2104. X            not_in_a_run = TRUE;
  2105. X        }
  2106. X    }
  2107. X
  2108. /* exit: */
  2109. X    avail = fast_buf - buf_ptr;
  2110. X    total_bytes += avail;
  2111. X    buf_start[-1] = fast_buf[-1];
  2112. X    line_ptr = fast_line;
  2113. X    save_state = state68;
  2114. X    save_accum = accum;
  2115. X
  2116. X    return avail;
  2117. X
  2118. }
  2119. X
  2120. non_suspect(start, beyond)
  2121. X    char *start;
  2122. X    char *beyond;
  2123. {
  2124. X    int looking_good;
  2125. X    int len;
  2126. X    register char *cp;
  2127. X    register char *last;
  2128. X    char *skip_msg = "Warning: skipping legal but suspect line in hqx file";
  2129. X
  2130. X    /* ensure it's long enough */
  2131. X    len = beyond - start;
  2132. X    looking_good = len >= suspect_shorter;
  2133. X    DEBUG && fprintf(debug, "DEBUG: non_suspect: long enough: %d\n",
  2134. X        looking_good);
  2135. X    DEBUG && fflush(debug);
  2136. X    if (!looking_good) {
  2137. X        fprintf(verbose, "%s -- line too short (%d < %d)\n",
  2138. X            skip_msg, len, suspect_shorter);
  2139. X        fflush(verbose);
  2140. X    }
  2141. X
  2142. X    /* ensure it's different enough */
  2143. X    if (suspect_same && looking_good) {
  2144. X        last = beyond - 1;
  2145. X        for (cp = start; cp < last; cp++)
  2146. X            if (*cp != *last) {
  2147. X                break;
  2148. X            }
  2149. X        /* is different */
  2150. X        looking_good = cp != last;
  2151. X        DEBUG && fprintf(debug,
  2152. X            "DEBUG: non_suspect: different enough: %d\n",
  2153. X            looking_good);
  2154. X        DEBUG && fflush(debug);
  2155. X        if (!looking_good) {
  2156. X            if (*last IS_LEGAL) {
  2157. X                fprintf(verbose, "%s -- all one input char ('%c')\n",
  2158. X                    skip_msg, tr86[*last] );
  2159. X            } else {
  2160. X                fprintf(verbose, "%s -- all chars mapped to 0x%02x\n",
  2161. X                    skip_msg, *last );
  2162. X            }
  2163. X            fflush(verbose);
  2164. X        }
  2165. X    }
  2166. X
  2167. X    hqxsuspect = !looking_good;
  2168. X
  2169. X    return looking_good;
  2170. }
  2171. X
  2172. new_in_hqx_file()
  2173. {
  2174. X    extern char **hqxnames_left;
  2175. X    int result;
  2176. X    long len;
  2177. X
  2178. X    DEBUG && fprintf(debug, "entering new_in_hqx_file ...\n");
  2179. X    DEBUG && fflush(debug);
  2180. X
  2181. X    if (*hqxnames_left[0] == '\0' || *hqxnames_left[0] == '-') {
  2182. X        result = FALSE;
  2183. X        goto exit;
  2184. X    }
  2185. X
  2186. X    len = strlen(*hqxnames_left);
  2187. X    if (len >= sizeof(hqxfname))
  2188. X        error("Error: specified hqxfname is too long", "");
  2189. X    strcpy(hqxfname, *hqxnames_left++);
  2190. X    /*
  2191. X     * we used to use freopen,
  2192. X     * but now suffer the slight inefficiency of close/open
  2193. X     * to provide info_only and consistent handling
  2194. X     * with good software engineering methods
  2195. X     */
  2196. X    mclose(&hqxfile, "hqxfile");
  2197. X    hqxfile = mopen(hqxfname, ".hqx", "r");
  2198. X    hqxsuspect = 1;
  2199. X    (void)fgets(LINE_START, MAXLINE, hqxfile);
  2200. X    result = TRUE;
  2201. X
  2202. exit:
  2203. X    if (result == TRUE)
  2204. X        DEBUG && fprintf(debug, "... opened %s\n", hqxfname);
  2205. X    else
  2206. X        DEBUG && fprintf(debug, "... nothing to open\n");
  2207. X    DEBUG && fflush(debug);
  2208. X
  2209. X    return result;
  2210. }
  2211. X
  2212. /*
  2213. X *  This procedure transparently encodes and writes the hqx output.  
  2214. X *  It does run length and 8 to 6 encoding.
  2215. X */
  2216. empty_hqxbuf()
  2217. {
  2218. X    register ulong c, accum, last_c;
  2219. X    register byte *fast_buf, *fast_line;
  2220. X    register int state86, dont_look_for_runs = FALSE, run_length;
  2221. X    extern int maxlines;
  2222. X
  2223. X    run_length = save_run_length;
  2224. X    last_c = buf_start[-1];
  2225. X    fast_buf = buf_start;
  2226. X    fast_line = line_ptr;
  2227. X    state86 = save_state;
  2228. X    accum = save_accum;
  2229. X    while (fast_buf < buf_ptr) {
  2230. X        c = *fast_buf++;
  2231. X        if (dont_look_for_runs)
  2232. X            dont_look_for_runs = FALSE;
  2233. X        else if (last_c == c && run_length < MAXRUN) {
  2234. X            run_length++;
  2235. X            continue;
  2236. X        } else {
  2237. X            if (run_length > 1) {
  2238. X                --fast_buf;
  2239. X                if (run_length == 2 && last_c != RUNCHAR)
  2240. X                    c = last_c;
  2241. X                else {
  2242. X                    c = RUNCHAR;
  2243. X                    *--fast_buf = run_length;
  2244. X                    dont_look_for_runs = TRUE;
  2245. X                }
  2246. X                run_length = 1;
  2247. X            } else
  2248. X                last_c = c;
  2249. X            if (c == RUNCHAR && !dont_look_for_runs) {
  2250. X                *--fast_buf = 0;
  2251. X                dont_look_for_runs = TRUE;
  2252. X            }
  2253. X        }
  2254. X
  2255. X        if (fast_line == line_end) {
  2256. X            if (line_count++ == maxlines)
  2257. X                new_out_hqx_file();
  2258. X            fputs(LINE_START, hqxfile);
  2259. X            fast_line = line_start;
  2260. X        }
  2261. X        switch (state86++) {
  2262. X        case 0:
  2263. X            *fast_line++ = tr86[c >> 2];
  2264. X            accum = (c << 4) & 0x3f;
  2265. X            break;
  2266. X        case 1:
  2267. X            *fast_line++ = tr86[(c >> 4) | accum];
  2268. X            accum = (c << 2) & 0x3f;
  2269. X            break;
  2270. X        case 2:
  2271. X            *fast_line++ = tr86[(c >> 6) | accum];
  2272. X            if (fast_line == line_end) {
  2273. X                if (line_count++ == maxlines)
  2274. X                    new_out_hqx_file();
  2275. X                fputs(LINE_START, hqxfile);
  2276. X                fast_line = line_start;
  2277. X            }
  2278. X            *fast_line++ = tr86[c & 0x3f];
  2279. X            state86 = 0;
  2280. X            break;
  2281. X        }
  2282. X    }
  2283. X    save_run_length = run_length;
  2284. X    buf_start[-1] = last_c;
  2285. X    buf_ptr = buf_start;
  2286. X    line_ptr = fast_line;
  2287. X    save_state = state86;
  2288. X    save_accum = accum;
  2289. }
  2290. X
  2291. new_out_hqx_file()
  2292. {
  2293. X    char filename[SYSNAMELEN + 7];
  2294. X    extern int maxlines;
  2295. X
  2296. X    fprintf(hqxfile, "<<< End of Part %2d >>>\n", file_count);
  2297. X    mclose(&hqxfile, "hqxfile");
  2298. X    file_count++;
  2299. X    if (maxlines)
  2300. X        sprintf(filename, "%s%02d.hqx", hqxfname, file_count);
  2301. X    else
  2302. X        sprintf(filename, "%s.hqx", hqxfname);
  2303. X    hqxfile = mopen(filename, "", "w");
  2304. X    if (file_count > 1)
  2305. X        fprintf(hqxfile, "<<< Start of Part %2d >>>\n", file_count);
  2306. X    else
  2307. X        fprintf(hqxfile, "(This file must be converted with BinHex 4.0)\n\n");
  2308. X    line_count = 3;
  2309. }
  2310. X
  2311. check_hqx_crc(calc_crc, msg, name)
  2312. X    word calc_crc;
  2313. X    char msg[], name[];
  2314. X
  2315. {
  2316. X    word read_crc;
  2317. X
  2318. X    if (buf_ptr >= buf_end)
  2319. X        (void)fill_hqxbuf(0);
  2320. X    read_crc = *buf_ptr++ << 8;
  2321. X    if (buf_ptr >= buf_end)
  2322. X        (void)fill_hqxbuf(0);
  2323. X    read_crc |= *buf_ptr++;
  2324. X    if (read_crc != calc_crc)
  2325. X        error(msg, name);
  2326. }
  2327. X
  2328. write_hqx_crc(calc_crc)
  2329. X    word calc_crc;
  2330. {
  2331. X    if (buf_ptr == buf_end)
  2332. X        empty_hqxbuf();
  2333. X    *buf_ptr++ = calc_crc >> 8;
  2334. X    if (buf_ptr == buf_end)
  2335. X        empty_hqxbuf();
  2336. X    *buf_ptr++ = calc_crc;
  2337. }
  2338. X
  2339. un_hqx(unpit_flag)
  2340. X    int unpit_flag;
  2341. {
  2342. X    char type[5];    /* stuff EOS */
  2343. X    ulong hqx_datalen, hqx_rsrclen;
  2344. X    word un_pit();
  2345. X    int unpitting, bytes_read;
  2346. X    word calc_crc;
  2347. X    extern char **hqxnames_left;
  2348. X    int same_file_only = 0;
  2349. X    int active;
  2350. X
  2351. X    /* we read EOF on this to transision, so the stream must be valid */
  2352. X    hqxfile = devnull;
  2353. X    line_end = line_start + HQXLINELEN;
  2354. X    buf_end = buf_start + HQXBUFLEN;
  2355. X
  2356. X    while (1) {
  2357. X        total_bytes = 0;
  2358. X        line_ptr = line_start;
  2359. X        /* ensure that the line buffer is considered empty */
  2360. X        /* why we use SKIP and not newline, I'm not sure */
  2361. X        line_ptr[0] = SKIP;
  2362. X        save_state = 0;
  2363. X        save_run_length = 0;
  2364. X
  2365. X        active = hqx_to_bin_hdr(type, &hqx_datalen, &hqx_rsrclen, same_file_only);
  2366. X        if (active == 0)
  2367. X            break;
  2368. X        same_file_only = 1;
  2369. X        type[4] = 0; /* set EOS */
  2370. X
  2371. X        unpitting = unpit_flag && !strcmp(type, "PIT ");
  2372. X        DEBUG && fprintf(debug,
  2373. X            "DEBUG: unpit_flag=%d type=%s unpitting=%d\n",
  2374. X            unpit_flag, type, unpitting);
  2375. X        DEBUG && fflush(debug);
  2376. X        if (unpitting) {
  2377. X            mclose(&binfile, "binfile");
  2378. X            /* Do not unlink files we did not open */
  2379. X           if (!info_only)
  2380. X                unlink(binfname);
  2381. X            bytes_read = total_bytes - (buf_end - buf_ptr);
  2382. X            calc_crc = un_pit();
  2383. X            bytes_read = total_bytes - (buf_end - buf_ptr) - bytes_read;
  2384. X            if (bytes_read != hqx_datalen) {
  2385. X                fprintf(verbose,
  2386. X                    "Warning - Extraneous characters ignored in %s\n", binfname);
  2387. X                fflush(verbose);
  2388. X            }
  2389. X        } else {
  2390. X            calc_crc = hqx_to_bin_fork(hqx_datalen);
  2391. X        }
  2392. X        check_hqx_crc(calc_crc, "File data CRC mismatch in %s", binfname);
  2393. X
  2394. X        calc_crc = hqx_to_bin_fork(hqx_rsrclen);
  2395. X        check_hqx_crc(calc_crc, "File rsrc CRC mismatch in %s", binfname);
  2396. X
  2397. X        if (!unpitting) {
  2398. X            mclose(&binfile, "binfile");
  2399. X        }
  2400. X
  2401. X    }
  2402. X    mclose(&hqxfile, "hqxfile");
  2403. }
  2404. X
  2405. re_hqx()
  2406. {
  2407. X    word calc_crc;
  2408. X    ulong hqx_datalen, hqx_rsrclen;
  2409. X    extern char **hqxnames_left;
  2410. X    extern int maxlines;
  2411. X
  2412. X    line_end = line_start + HQXLINELEN;
  2413. X    buf_end = buf_start + HQXBUFLEN;
  2414. X    while (*hqxnames_left[0] != '-') {
  2415. X        /* we write the trailer, so the stream must be valid */
  2416. X        hqxfile = devnull;
  2417. X
  2418. X        /*
  2419. X       * We use the trick of setting our line_count at the limit to
  2420. X       * force an immediate transition on overflow.
  2421. X         */
  2422. X        line_count = maxlines;
  2423. X
  2424. X        file_count = 0;
  2425. X        line_ptr = line_start;
  2426. X        *line_ptr++ = ':';
  2427. X        strcpy((char*)line_end, "\n");
  2428. X        buf_ptr = buf_start;
  2429. X        save_state = 0;
  2430. X        save_run_length = 1;
  2431. X
  2432. X        bin_to_hqx_hdr(&hqx_datalen, &hqx_rsrclen);    /* calculates hqxfname */
  2433. X
  2434. X        /*
  2435. X       * Now that we have hqxfname, start the new file if
  2436. X         * not yet started.  We no longer wait until the output
  2437. X         * buffer overflows, since empty files with short names didn't overflow!
  2438. X         */
  2439. X
  2440. X        if (file_count == 0)
  2441. X            new_out_hqx_file();
  2442. X
  2443. X        calc_crc = bin_to_hqx_fork(hqx_datalen);
  2444. X        write_hqx_crc(calc_crc);
  2445. X
  2446. X        calc_crc = bin_to_hqx_fork(hqx_rsrclen);
  2447. X        write_hqx_crc(calc_crc);
  2448. X        /*
  2449. X       * To end a run and to get the last stray bits,
  2450. X         * temporarily add a char.
  2451. X         */
  2452. X        *buf_ptr = !buf_ptr[-1];
  2453. X        buf_ptr++;
  2454. X        empty_hqxbuf();
  2455. X        /* now toss any extra output character generated */
  2456. X        if (save_state != 2)
  2457. X            --line_ptr;
  2458. X
  2459. X        /* if we're at the end of the line now, write it out */
  2460. X        if (line_ptr == line_end) {
  2461. X            fputs(LINE_START, hqxfile);
  2462. X            line_ptr = line_start;
  2463. X        }
  2464. X
  2465. X        /* paste the trailing colon onto the end of the line */
  2466. X        /* recall that line_ptr points into the line, not at the line */
  2467. X        strcpy((char*)line_ptr, ":\n");
  2468. X        
  2469. X        /* and flush the output buffer */
  2470. X        fputs(LINE_START, hqxfile);
  2471. X
  2472. X        mclose(&hqxfile, "hqxfile");
  2473. X        mclose(&binfile, "binfile");
  2474. X
  2475. X    }
  2476. }
  2477. X
  2478. SHAR_EOF
  2479. chmod 0444 hqxify.c ||
  2480. echo 'restore of hqxify.c failed'
  2481. Wc_c="`wc -c < 'hqxify.c'`"
  2482. test 28300 -eq "$Wc_c" ||
  2483.     echo 'hqxify.c: original size 28300, current size' "$Wc_c"
  2484. fi
  2485. # ============= unpack.c ==============
  2486. if test -f 'unpack.c' -a X"$1" != X"-c"; then
  2487.     echo 'x - skipping unpack.c (File already exists)'
  2488. else
  2489. echo 'x - extracting unpack.c (Text)'
  2490. sed 's/^X//' << 'SHAR_EOF' > 'unpack.c' &&
  2491. #include "mactypes.h"
  2492. X
  2493. extern word magic[];
  2494. extern char *dir, *ext;
  2495. extern int info_only;
  2496. X
  2497. ulong pit_datalen, pit_rsrclen;
  2498. word hqx_crc, write_pit_fork();
  2499. char pitfname[SYSNAMELEN];    /* name of file being unpacked */
  2500. FILE *pitfile;            /* output file */
  2501. X
  2502. branch branchlist[255], *branchptr, *read_tree();
  2503. leaf leaflist[256], *leafptr;
  2504. word Huff_nibble, Huff_bit_count;
  2505. X
  2506. byte(*read_char) (), get_crc_byte(), getHuffbyte();
  2507. X
  2508. word 
  2509. un_pit()
  2510. {
  2511. X    char PitId[4];
  2512. X    int i;
  2513. X    word pit_crc;
  2514. X
  2515. X    hqx_crc = 0;
  2516. X    /* Read and unpack until the PackIt End message is read */
  2517. X    for (;;) {
  2518. X        read_char = get_crc_byte;
  2519. X        for (i = 0; i < 4; i++)
  2520. X            PitId[i] = (char) get_crc_byte();
  2521. X        if (!strncmp(PitId, "PEnd", 4))
  2522. X            break;
  2523. X
  2524. X        if (strncmp(PitId, "PMag", 4) && strncmp(PitId, "PMa4", 4))
  2525. X            error("Unrecognized Packit format message %s", PitId);
  2526. X
  2527. X        if (PitId[3] == '4') {
  2528. X            /* if this file is compressed */
  2529. X            /* read the Huffman decoding  */
  2530. X            /* tree that is on the input  */
  2531. X            /* and use Huffman decoding   */
  2532. X            /* subsequently               */
  2533. X            branchptr = branchlist;
  2534. X            leafptr = leaflist;
  2535. X            Huff_bit_count = 0;
  2536. X            (void)read_tree();
  2537. X            read_char = getHuffbyte;
  2538. X        }
  2539. X        read_pit_hdr();               /* also calculates datalen,
  2540. X                            * rsrclen, pitfile, pitfname */
  2541. X        pit_crc = write_pit_fork(pit_datalen, (ulong)0);
  2542. X        pit_crc = write_pit_fork(pit_rsrclen, (ulong)pit_crc);
  2543. X        check_pit_crc(pit_crc, "  File data/rsrc CRC mismatch in %s", pitfname);
  2544. X        mclose(&pitfile, "pitfile");
  2545. X    }
  2546. X    hqx_crc = (hqx_crc << 8) ^ magic[hqx_crc >> 8];
  2547. X    hqx_crc = (hqx_crc << 8) ^ magic[hqx_crc >> 8];
  2548. X    return hqx_crc;
  2549. }
  2550. X
  2551. check_pit_crc(calc_crc, msg, name)
  2552. X    word calc_crc;
  2553. X    char msg[], name[];
  2554. X
  2555. {
  2556. X    word read_crc;
  2557. X
  2558. X    read_crc = (*read_char) () << 8;
  2559. X    read_crc |= (*read_char) ();
  2560. X    if (read_crc != calc_crc)
  2561. X        error(msg, name);
  2562. }
  2563. X
  2564. /*  
  2565. X * This routine reads the header of a packed file and appropriately
  2566. X * twiddles it, determines if it has CRC problems, creates the .bin
  2567. X * file, and puts the info into the .bin file.  Output is
  2568. X * pit_datalen, pit_rsrclen, pitfname, pitfile
  2569. X */
  2570. read_pit_hdr()
  2571. {
  2572. X    register int n;
  2573. X    register byte *pit_byte;
  2574. X    register ulong pit_crc;
  2575. X    pit_header pit;
  2576. X    info_header info;
  2577. X    short crc;
  2578. X    char *action;
  2579. X    long len;
  2580. X
  2581. X    extern short calc_mb_crc();
  2582. X
  2583. X    /* read the pit header and compute the CRC */
  2584. X    pit_crc = 0;
  2585. X    pit_byte = (byte *) & pit;
  2586. X    for (n = 0; n < sizeof(pit_header); n++) {
  2587. X        *pit_byte = (*read_char) ();
  2588. X        pit_crc = ((pit_crc & 0xff) << 8)
  2589. X            ^ magic[*pit_byte++ ^ (pit_crc >> 8)];
  2590. X    }
  2591. X
  2592. X    /* stuff the pit header data into the info header */
  2593. X    bzero((char*)&info, sizeof(info_header));
  2594. X    info.nlen = pit.nlen;
  2595. X    if (pit.nlen > sizeof(info.name))
  2596. X        error("Error: corrupt PIT data format", "");
  2597. X    /*
  2598. X     * expect a valid Macintosh file name since it came from a PIT file
  2599. X     * and don't potentially corrupt a valid copied name via macify
  2600. X     */
  2601. X    strncpy((char*)info.name, (char*)pit.name, (int)pit.nlen);/* name */
  2602. X    bcopy((char*)pit.type, (char*)info.type, 9);  /* type, author, flag */
  2603. X    bcopy((char*)pit.dlen, (char*)info.dlen, 16); /* (d,r)len, (c,m)tim */
  2604. X    info.flags &= 0x7e;               /* reset lock bit, init bit */
  2605. X    if (pit.protect & 0x40)
  2606. X        info.protect = 1;           /* copy protect bit */
  2607. X    info.uploadvers = '\201';
  2608. X    info.readvers = '\201';
  2609. X
  2610. X    /* calculate MacBinary CRC */
  2611. X    crc = calc_mb_crc((unsigned char*)&info, 124L, 0);
  2612. X    info.crc[0] = (char) (crc >> 8);
  2613. X    info.crc[1] = (char) crc;
  2614. X
  2615. X    /* Create the .bin file and write the info to it */
  2616. X    pit.name[pit.nlen] = '\0';
  2617. X    unixify((char*)pit.name);
  2618. X
  2619. X    len = strlen(dir) + strlen((char*)pit.name) + strlen(ext) + 1;
  2620. X    if (len >= sizeof(pitfname))
  2621. X        error("Error: generated pitfname would be too long", "");
  2622. X    sprintf(pitfname, "%s/%s%s", dir, pit.name, ext);
  2623. X
  2624. X    if (info_only)
  2625. X        action = (read_char == get_crc_byte) ? "Packed" : "Compressed";
  2626. X    else
  2627. X        action = (read_char == get_crc_byte) ? "Unpacking" : "Decompressing";
  2628. X
  2629. X    fprintf(convert, " %-14s%-30s type = \"%4.4s\", author = \"%4.4s\"\n",
  2630. X        action, pit.name, pit.type, pit.auth);
  2631. X    fflush(convert);
  2632. X    print_bin_hdr("Creating", &info);
  2633. X    pitfile = mopen(pitfname, "", "w");
  2634. X    check_pit_crc((word)pit_crc, "  File header CRC mismatch in %s", pitfname);
  2635. X    if (1 != fwrite((char*)&info, sizeof(info_header), 1, pitfile))
  2636. X        error("fwrite failed on pitfile", "");
  2637. X
  2638. X    /* Get a couple of items we'll need later */
  2639. X    bcopy((char*)pit.dlen, (char*)&pit_datalen, 4);
  2640. X    pit_datalen = mac2long(pit_datalen);
  2641. X    bcopy((char*)pit.rlen, (char*)&pit_rsrclen, 4);
  2642. X    pit_rsrclen = mac2long(pit_rsrclen);
  2643. }
  2644. X
  2645. /* This routine copies bytes from the decoded input stream to the output
  2646. X    and calculates the CRC.  It also pads to a multiple of 128 bytes on the
  2647. X    output, which is part of the .bin format */
  2648. word 
  2649. write_pit_fork(nbytes, calc_crc)
  2650. X    register ulong nbytes;
  2651. X    register ulong calc_crc;
  2652. {
  2653. X    register ulong b;
  2654. X    int extra_bytes;
  2655. X
  2656. X    /* pad fork to mult of * 128 bytes */
  2657. X    extra_bytes = 127 - (nbytes + 127) % 128;
  2658. X    while (nbytes--) {
  2659. X        b = (*read_char) ();
  2660. X        calc_crc = ((calc_crc & 0xff) << 8) ^ magic[b ^ (calc_crc >> 8)];
  2661. X        if (EOF == putc((char)b, pitfile))
  2662. X            error("Error: putc failed on pitfile", "");
  2663. X    }
  2664. X    while (extra_bytes--)
  2665. X        if (EOF == putc(0, pitfile))
  2666. X            error("Error: putc failed on pitfile", "");
  2667. X    return (word) calc_crc;
  2668. }
  2669. X
  2670. /* This routine recursively reads the compression decoding data.
  2671. X   It appears to be Huffman compression.  Every leaf is represented
  2672. X   by a 1 bit, then the byte it represents.  A branch is represented
  2673. X   by a 0 bit, then its zero and one sons */
  2674. branch *
  2675. read_tree()
  2676. {
  2677. X    register branch *branchp;
  2678. X    register leaf *leafp;
  2679. X    register ulong b;
  2680. X
  2681. X    if (!Huff_bit_count--) {
  2682. X        Huff_nibble = get_crc_byte();
  2683. X        Huff_bit_count = 7;
  2684. X    }
  2685. X    if ((Huff_nibble <<= 1) & 0x0100) {
  2686. X        leafp = leafptr++;
  2687. X        leafp->flag = 1;
  2688. X        b = get_crc_byte();
  2689. X        leafp->data = Huff_nibble | (b >> Huff_bit_count);
  2690. X        Huff_nibble = b << (8 - Huff_bit_count);
  2691. X        return (branch *) leafp;
  2692. X    } else {
  2693. X        branchp = branchptr++;
  2694. X        branchp->flag = 0;
  2695. X        branchp->zero = read_tree();
  2696. X        branchp->one = read_tree();
  2697. X        return branchp;
  2698. X    }
  2699. }
  2700. X
  2701. /* This routine returns the next 8 bits.  It finds the byte in the
  2702. X   Huffman decoding tree based on the bits from the input stream. */
  2703. byte 
  2704. getHuffbyte()
  2705. {
  2706. X    register branch *branchp;
  2707. X
  2708. X    branchp = branchlist;
  2709. X    while (!branchp->flag) {
  2710. X        if (!Huff_bit_count--) {
  2711. X            Huff_nibble = get_crc_byte();
  2712. X            Huff_bit_count = 7;
  2713. X        }
  2714. X        branchp = ((Huff_nibble <<= 1) & 0x0100) ? branchp->one : branchp->zero;
  2715. X    }
  2716. X    return ((leaf *) branchp)->data;
  2717. }
  2718. X
  2719. /* This routine returns the next byte on the .hqx input stream, hiding
  2720. X    most file system details at a lower level.  .hqx CRC is maintained
  2721. X    here */
  2722. byte 
  2723. get_crc_byte()
  2724. {
  2725. X    register ulong c;
  2726. X    extern byte *buf_ptr, *buf_end;
  2727. X
  2728. X    if (buf_ptr == buf_end) {
  2729. X        if (fill_hqxbuf(0) == 0)
  2730. X            error("premature EOF reading PIT info from BinHex 4.0 file", "");
  2731. X    }
  2732. X    c = *buf_ptr++;
  2733. X    hqx_crc = ((hqx_crc << 8) | c) ^ magic[hqx_crc >> 8];
  2734. X    return (byte) c;
  2735. }
  2736. SHAR_EOF
  2737. chmod 0444 unpack.c ||
  2738. echo 'restore of unpack.c failed'
  2739. Wc_c="`wc -c < 'unpack.c'`"
  2740. test 6868 -eq "$Wc_c" ||
  2741.     echo 'unpack.c: original size 6868, current size' "$Wc_c"
  2742. fi
  2743. # ============= mactypes.h ==============
  2744. if test -f 'mactypes.h' -a X"$1" != X"-c"; then
  2745.     echo 'x - skipping mactypes.h (File already exists)'
  2746. else
  2747. echo 'x - extracting mactypes.h (Text)'
  2748. sed 's/^X//' << 'SHAR_EOF' > 'mactypes.h' &&
  2749. #include <stdio.h>
  2750. #include <sys/types.h>
  2751. #include <sys/dir.h>
  2752. #include <sys/stat.h>
  2753. X
  2754. #ifdef TIMEVAL
  2755. #  include <sys/param.h>
  2756. #  include <sys/time.h>
  2757. #else
  2758. #  include <sys/timeb.h>
  2759. #endif
  2760. X
  2761. typedef unsigned char byte;     /* one byte, obviously */
  2762. typedef unsigned short word;    /* must be 2 bytes */
  2763. #ifndef ULONG
  2764. X    typedef unsigned long ulong; /* 4 bytes */
  2765. #endif
  2766. X
  2767. /* declarations to keep lint informed */
  2768. char *calloc();
  2769. #include <string.h>
  2770. void exit();
  2771. long time();
  2772. ulong unix2mac();
  2773. ulong mac2unix();
  2774. char *ctime();
  2775. FILE *mopen();
  2776. X
  2777. #define TRUE  1
  2778. #define FALSE 0
  2779. #define CR 0x0d
  2780. #define LF 0x0a
  2781. X
  2782. /* various files and debug options */
  2783. extern FILE *devnull;    /* constant /dev/null for bit bucket output */
  2784. extern FILE *convert;    /* convert messages */
  2785. extern FILE *verbose;    /* verbose output */
  2786. extern FILE *debug;    /* debug output */
  2787. extern int   Debug;    /* debug level */
  2788. #define DEBUG (debug != devnull)
  2789. X
  2790. /* Compatibility issues */
  2791. X
  2792. #ifdef NOBYTEORDER
  2793. #define mac2word
  2794. #define mac2long
  2795. #define word2mac
  2796. #define long2mac
  2797. #else
  2798. #include <netinet/in.h>
  2799. #define mac2word (word) ntohs
  2800. #define mac2long (ulong) ntohl
  2801. #define word2mac (word) htons
  2802. #define long2mac (ulong) htonl
  2803. #endif
  2804. X
  2805. #ifdef NOBZEROBCOPY
  2806. #define bzero(dst,len) (memset(dst,0,len))
  2807. #define bcopy(src,dst,len) (memcpy(dst,src,len))
  2808. #endif
  2809. X
  2810. #define MAXEXTENSION 5          /* max(".bin", ".text", ".data", ".rsrc") */
  2811. #define SYSNAMELEN 1024         /* reasonable UNIX working name length */
  2812. #define NAMELEN 63              /* maximum legal Mac file name length */
  2813. X
  2814. /* Format of a bin file:
  2815. A bin file is composed of 128 byte blocks.  The first block is the
  2816. info_header (see below).  Then comes the data fork, null padded to fill the
  2817. last block.  Then comes the resource fork, padded to fill the last block.  A
  2818. proposal to follow with the text of the Get Info box has not been implemented,
  2819. to the best of my knowledge.  Version, zero1 and zero2 are what the receiving
  2820. program looks at to determine if a MacBinary transfer is being initiated.
  2821. */
  2822. X
  2823. /* info file header (128 bytes) */
  2824. typedef struct {
  2825. X    /* Unfortunately, the longs don't align to word boundaries */
  2826. X
  2827. /* decimal offset */
  2828. X
  2829. /* 000 */
  2830. X        byte version;           /* there is only a version 0 at this time */
  2831. /* 001 */
  2832. X        byte nlen;              /* Length of filename. */
  2833. /* 002 */
  2834. X        byte name[NAMELEN];     /* Filename (only 1st nlen are significant) */
  2835. /* 065 */
  2836. X        byte type[4];           /* File type. */
  2837. /* 069 */
  2838. X        byte auth[4];           /* File creator. */
  2839. /* 073 */
  2840. X        byte flags;             /* file flags: LkIvBnSyBzByChIt */
  2841. X                                /* Locked, Invisible,Bundle, System */
  2842. X                                /* Bozo, Busy, Changed, Init */
  2843. /* 074 */
  2844. X        byte zero1;
  2845. /* 075 */
  2846. X        byte icon_vert[2];      /* Vertical icon position within window */
  2847. /* 077 */
  2848. X        byte icon_horiz[2];     /* Horizontal icon postion in window */
  2849. /* 079 */
  2850. X        byte window_id[2];      /* Window or folder ID. */
  2851. /* 081 */
  2852. X        byte protect;           /* = 1 for protected file, 0 otherwise */
  2853. /* 082 */
  2854. X        byte zero2;
  2855. /* 083 */
  2856. X        byte dlen[4];           /* Data Fork length (bytes) -   most sig.  */
  2857. /* 087 */
  2858. X        byte rlen[4];           /* Resource Fork length         byte first */
  2859. /* 091 */
  2860. X        byte ctim[4];           /* File's creation date. */
  2861. /* 095 */
  2862. X        byte mtim[4];           /* File's "last modified" date. */
  2863. /* 099 */
  2864. X        byte ilen[2];           /* GetInfo message length */
  2865. /* 101 */
  2866. X        byte flags2;            /* Finder flags, bits 0-7 */
  2867. /* 102 */
  2868. X        byte unused[14];
  2869. /* 116 */
  2870. X        byte packlen[4];        /* length of total files when unpacked */
  2871. /* 120 */
  2872. X        byte headlen[2];        /* length of secondary header */
  2873. /* 122 */
  2874. X        byte uploadvers;        /* Version of MacBinary II that the uploading
  2875. X                                 * program is written for */
  2876. /* 123 */
  2877. X        byte readvers;          /* Minimum MacBinary II version needed to read
  2878. X                                 * this file */
  2879. /* 124 */
  2880. X        byte crc[2];            /* CRC of the previous 124 bytes */
  2881. /* 126 */
  2882. X        byte padding[2];        /* two trailing unused bytes */
  2883. /* 128 */
  2884. }      info_header;
  2885. X
  2886. /* The *.info file of a MacTerminal file transfer either has exactly this
  2887. structure or has the protect bit in bit 6 (near the sign bit) of byte zero1.
  2888. The code I have for macbin suggests the difference, but I'm not so sure */
  2889. X
  2890. /*
  2891. X * Format of a hqx file:
  2892. X * (but see also binhex-40-specs.txt for legal variations)
  2893. X * 
  2894. X * It begins with a line that begins "(This file" and the rest is 64
  2895. X * character lines (except possibly the last, and not including
  2896. X * newlines) where the first begins and the last ends with a colon.
  2897. X * The characters between colons should be only from the set in tr86,
  2898. X * below, each of which corresponds to 6 bits of data.  Once that is
  2899. X * translated to 8 bit bytes, you have the real data, except that the
  2900. X * byte 0x90 may indicate, if the following character is nonzero, that
  2901. X * the previous byte is to be repeated 1 to 255 times all together
  2902. X * (that is, the count following 0x90 contains the total run length,
  2903. X * not the marginal repeat count).  The byte 0x90 is represented by
  2904. X * 0x9000.  The information in the file is the hqx_buf (see below), a
  2905. X * CRC word, the data fork, a CRC word, the resource fork, and a CRC
  2906. X * word.  There is considerable confusion about the flags.  An
  2907. X * official looking document unclearly states that the init bit is
  2908. X * always clear, as is the following byte.  The experience of others
  2909. X * suggests, however, that this is not the case.
  2910. X */
  2911. X
  2912. /* NOTE:
  2913. X * Jskud 25Jun92
  2914. X
  2915. X * a hqx file has no date/time information, and a binary constructed
  2916. X * from a hqx file will use the current time; therefore, reconverting
  2917. X * a hqx file repeatedly will generate different bin files!
  2918. X
  2919. X * The "flags" byte can change when refetched, for example, whether or
  2920. X * not the init bit is set (that is, the Finder has "seen" the file);
  2921. X * this can affect the hqx file, including the run length encoding, so
  2922. X * the hqx files can look quite different, although the actual
  2923. X * difference is miniscule; also, the init bit difference will not be
  2924. X * present when the hqx file is converted to a bin file, since both the
  2925. X * locked and init bits are cleared on bin file creation.
  2926. X
  2927. X * Because we've experienced this "spurious" difference, and since
  2928. X * the init bit is only thought meaningful when running on the Mac,
  2929. X * and to establish symmetry between bin file creation and hqx file
  2930. X * creation, we unconditionally clear the init and locked bits when
  2931. X * creating the hqx file.
  2932. X
  2933. X */
  2934. X
  2935. #define HQXLINELEN 64
  2936. typedef struct {
  2937. /* decimal offset */
  2938. /* 000 */
  2939. X        byte version;           /* there is only a version 0 at this time */
  2940. /* 001 */
  2941. X        byte type[4];           /* File type. */
  2942. /* 005 */
  2943. X        byte auth[4];           /* File creator. */
  2944. /* 009 */
  2945. X        byte flags;             /* file flags: LkIvBnSyBzByChIt */
  2946. /* 010 */
  2947. X        byte protect;           /* ?Pr??????, don't know what ? bits mean */
  2948. /* 011 */
  2949. X        byte dlen[4];           /* Data Fork length (bytes) -   most sig.  */
  2950. /* 015 */
  2951. X        byte rlen[4];           /* Resource Fork length         byte first */
  2952. /* 019 */
  2953. X        byte bugblank;          /* to fix obscure sun 3/60 problem that always
  2954. X                                 * makes sizeof(hqx_header) even */
  2955. /* 020 */
  2956. }      hqx_header;
  2957. X
  2958. /* hqx file header buffer (includes file name) */
  2959. typedef struct {
  2960. X        byte nlen;              /* Length of filename. */
  2961. X        byte name[NAMELEN];     /* Filename: only nlen actually appear */
  2962. X        hqx_header all_the_rest;/* and all the rest follows immediately */
  2963. }      hqx_buf;
  2964. X
  2965. /* every valid hqx header is at least this long */
  2966. #define MIN_HQX_HDR (sizeof(hqx_header) + 2)
  2967. X
  2968. /*
  2969. X *    The minimum number of hqx_lines in a file to ensure that we have
  2970. X *    enough lines to emit the entire header before starting a new file.
  2971. X * + 1 is for rounding, + 2 is for "(This file " and the blank line.
  2972. X */
  2973. #define MIN_HQX_LINES (sizeof(hqx_buf) * 4 / 3 / HQXLINELEN + 1 + 2)
  2974. X
  2975. X
  2976. /* Format of a Packit file:
  2977. Repeat the following sequence for each file in the Packit file:
  2978. X    4 byte identifier ("PMag" = not compressed, "Pma4" = compressed)
  2979. X    320 byte compression data (if compressed file)
  2980. X        = preorder transversal of Huffman tree
  2981. X        255 0 bits corresponding to nonleaf nodes
  2982. X        256 1 bits corresponding to leaf nodes
  2983. X        256 bytes associating leaf nodes with bytes
  2984. X        1   completely wasted bit
  2985. X    92 byte header (see pit_header below) *
  2986. X    2 bytes CRC word for header *
  2987. X    data fork (length from header) *
  2988. X    resource fork (length from header) *
  2989. X    2 bytes CRC word for forks *
  2990. X
  2991. Last file is followed by the 4 byte Ascii string, "Pend", and then the EOF.
  2992. The CRC calculations differ from those in the binhex format.
  2993. X
  2994. * these are in compressed form if compression is on for the file
  2995. X
  2996. */
  2997. X
  2998. typedef struct {                /* Packit file header (92 bytes) */
  2999. X        byte nlen;              /* Length of filename. */
  3000. X        byte name[NAMELEN];     /* Filename (only 1st nlen are significant) */
  3001. X        byte type[4];           /* File type. */
  3002. X        byte auth[4];           /* File creator. */
  3003. X        byte flags;             /* file flags: LkIvBnSyBzByChIt */
  3004. X        byte zero1;
  3005. X        byte protect;           /* = 1 for protected file, 0 otherwise */
  3006. X        byte zero2;
  3007. X        byte dlen[4];           /* Data Fork length (bytes) -   most sig.  */
  3008. X        byte rlen[4];           /* Resource Fork length         byte first */
  3009. X        byte ctim[4];           /* File's creation date. */
  3010. X        byte mtim[4];           /* File's "last modified" date. */
  3011. }      pit_header;
  3012. X
  3013. /* types for constructing the Huffman tree */
  3014. typedef struct branch_st {
  3015. X        byte flag;
  3016. X        struct branch_st *one, *zero;
  3017. }         branch;
  3018. X
  3019. typedef struct leaf_st {
  3020. X        byte flag;
  3021. X        byte data;
  3022. }       leaf;
  3023. SHAR_EOF
  3024. chmod 0444 mactypes.h ||
  3025. echo 'restore of mactypes.h failed'
  3026. Wc_c="`wc -c < 'mactypes.h'`"
  3027. test 9956 -eq "$Wc_c" ||
  3028.     echo 'mactypes.h: original size 9956, current size' "$Wc_c"
  3029. fi
  3030. # ============= Makefile ==============
  3031. if test -f 'Makefile' -a X"$1" != X"-c"; then
  3032.     echo 'x - skipping Makefile (File already exists)'
  3033. else
  3034. echo 'x - extracting Makefile (Text)'
  3035. sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
  3036. ## This file is formatted with a tab-width of 3
  3037. X
  3038. ## See the README file for hints how to configure this Makefile.
  3039. X
  3040. CSOURCES    = mcvert.c hqxify.c unpack.c
  3041. HSOURCES    = mactypes.h
  3042. SOURCES     = $(CSOURCES) $(HSOURCES) \
  3043. X              Makefile README README-conversion mcvert.idraw mcvert.1
  3044. MANIFEST    = $(SOURCES) mcvert.man
  3045. OBJECTS     = mcvert.o hqxify.o unpack.o $(XOBJ)
  3046. ALL         = mcvert mcvert.man
  3047. EVERYTHING  = $(ALL) shar mcvert.ps
  3048. CLEAN       = $(OBJECTS) $(EVERYTHING)
  3049. X
  3050. VERSION=215
  3051. X
  3052. BIN = .
  3053. X
  3054. ##
  3055. ## *LAST* Defintion Always Wins ##
  3056. ##
  3057. X
  3058. ## Note: when using -lnet, AT&T 3B2 fails with undefined symbols like
  3059. ##       t_errno first used in /usr/lib/libnet.a
  3060. ##    so extract gettod.o and explicitly bind it in
  3061. X
  3062. ### Extra Objects
  3063. # for AT&T 3B2
  3064. XXOBJ= gettod.o
  3065. # common case
  3066. XXOBJ=
  3067. X
  3068. ### Bind Time Library Selection
  3069. # for SCO UNIX 3.2v4.1 with SCO TCPIP 1.2.0
  3070. LIBS= -lsocket
  3071. # for most implementations
  3072. LIBS=
  3073. X
  3074. ## Note that ftime() is obsolete, and has been replaced by gettimeofday()
  3075. ## so, in general, you should be using -DTIMEVAL
  3076. ## but I am not  able  to test this  on all platforms  on all releases,
  3077. ## so we leave the aging recipe in place
  3078. X
  3079. ### Machine CFLAGS
  3080. ## for machines with <timeb.h> and ftime() [and maybe without gettimeofday()]
  3081. # eg: works for ULTRIX
  3082. CFLAGS_M=
  3083. ## for machines with ulong pre-defined
  3084. CFLAGS_M= -DULONG
  3085. # eg: A/UX, SGI's Irix, AT&T 3B2, IBM RS/6000's AIX
  3086. CFLAGS_M= -DTIMEVAL -DULONG
  3087. ## for machines with gettimeofday() [and maybe without <timeb.h> and ftime()]
  3088. # eg: HP-UX 9.01, SunOS 4.1.3, DomainOS 10.4
  3089. CFLAGS_M= -DTIMEVAL
  3090. X
  3091. ### Byteorder(3n) [eg: htonl()] and Byte Manipulation [eg: bzero, bcopy] CFLAGS
  3092. # uncommon case -- without support, eg: AT&T 3B2
  3093. CFLAGS_N = -DNOBYTEORDER -DNOBZEROBCOPY
  3094. # unknown case 1
  3095. CFLAGS_N = -DNOBYTEORDER
  3096. # unknown case 2
  3097. CFLAGS_N = -DNOBZEROBCOPY
  3098. # common case -- with support for  both
  3099. CFLAGS_N =
  3100. X
  3101. ### Debugging/Optimization CFLAGS
  3102. # debugging
  3103. CFLAGS_D = -g
  3104. # optimization
  3105. CFLAGS_D = -O
  3106. X
  3107. ### All CFLAGS
  3108. CFLAGS=$(CFLAGS_M) $(CFLAGS_N) $(CFLAGS_D) -DVERSION=$(VERSION)
  3109. X
  3110. ### lint related
  3111. LINT=lint
  3112. LFLAGS=$(CFLAGS_M) $(CFLAGS_N) -DVERSION=$(VERSION)
  3113. X
  3114. all: $(ALL)
  3115. everything: $(EVERYTHING)
  3116. X
  3117. mcvert: $(OBJECTS)
  3118. X    $(CC) $(CFLAGS) $(OBJECTS) $(LIBS) -o $(BIN)/mcvert
  3119. X
  3120. lint: $(HSOURCES) $(CSOURCES)
  3121. X    $(LINT) $(LFLAGS) $(CSOURCES)
  3122. X
  3123. $(SOURCES):
  3124. X    sccs get $@
  3125. X
  3126. gettod.o:
  3127. X    ar -xv /usr/lib/libnet.a $@
  3128. X
  3129. $(OBJECTS): mactypes.h Makefile
  3130. X
  3131. shar : mcvert-$(VERSION).shar
  3132. mcvert-$(VERSION).shar : $(MANIFEST) check_linelen
  3133. X    shar $(MANIFEST) > $@
  3134. X
  3135. # we punt the issue of expanding tabs
  3136. check_linelen: $(MANIFEST)
  3137. X    nawk 'length($0) >= 80 { printf "%s: %d: ", FILENAME, FNR; print }' \
  3138. X        $(MANIFEST)
  3139. X
  3140. clean:
  3141. X    rm -f $(CLEAN)
  3142. X
  3143. man: mcvert.man
  3144. mcvert.man: mcvert.1
  3145. X    nroff -man mcvert.1 | col | sed 's/.//g' | expand > $@
  3146. mcvert.ps: mcvert.1
  3147. X    groff -man mcvert.1 > $@
  3148. SHAR_EOF
  3149. chmod 0444 Makefile ||
  3150. echo 'restore of Makefile failed'
  3151. Wc_c="`wc -c < 'Makefile'`"
  3152. test 2811 -eq "$Wc_c" ||
  3153.     echo 'Makefile: original size 2811, current size' "$Wc_c"
  3154. fi
  3155. # ============= README ==============
  3156. if test -f 'README' -a X"$1" != X"-c"; then
  3157.     echo 'x - skipping README (File already exists)'
  3158. else
  3159. echo 'x - extracting README (Text)'
  3160. sed 's/^X//' << 'SHAR_EOF' > 'README' &&
  3161. mcvert needs to be compiled before you can run it, since mcvert runs on
  3162. a wide variety of machines, each with its own binary format.
  3163. X
  3164. o Ready a directory to hold mcvert
  3165. X
  3166. X    cd
  3167. X    mkdir mcvert
  3168. X    cp mcvert-nnn.shar mcvert
  3169. X    cd mcvert
  3170. X
  3171. o Create the individual files from the Shell Archive (shar) file
  3172. X
  3173. X    sh mcvert-nnn.shar
  3174. X
  3175. o Reorder the Makefile as appropriate for your machine
  3176. X
  3177. X  Note that there are a number of variables with which to fiddle,
  3178. X  and that the last definition wins.
  3179. X
  3180. X  For example, when compiling for AT&T's 3B2, reorder so these lines
  3181. X  are last within group:
  3182. X
  3183. X    XOBJ= gettod.o
  3184. X    
  3185. X    LIBS=
  3186. X
  3187. X    CFLAGS_M= -DTIMEVAL -DULONG
  3188. X
  3189. X    CFLAGS_N = -DNOBYTEORDER -DNOBZEROBCOPY
  3190. X
  3191. o Make the binary and man page
  3192. X
  3193. X    make
  3194. X
  3195. o Read the manpage for a full description
  3196. X
  3197. X    more mcvert.man
  3198. X
  3199. o Invoke the binary without arguments for a short description
  3200. X
  3201. X    mcvert
  3202. X
  3203. []
  3204. SHAR_EOF
  3205. chmod 0444 README ||
  3206. echo 'restore of README failed'
  3207. Wc_c="`wc -c < 'README'`"
  3208. test 842 -eq "$Wc_c" ||
  3209.     echo 'README: original size 842, current size' "$Wc_c"
  3210. fi
  3211. # ============= README-conversion ==============
  3212. if test -f 'README-conversion' -a X"$1" != X"-c"; then
  3213.     echo 'x - skipping README-conversion (File already exists)'
  3214. else
  3215. echo 'x - extracting README-conversion (Text)'
  3216. sed 's/^X//' << 'SHAR_EOF' > 'README-conversion' &&
  3217. Overview of file conversion
  3218. X
  3219. More details regarding file formats may be found in the mcvert.1 man
  3220. page, but basically, there are native Mac files that live (only) on
  3221. the Mac (since they have interesting internal structure), and
  3222. representations of Mac files.
  3223. X
  3224. One very important representation is called MacBinary.  It is nothing
  3225. but "data".  But it is 8-bit data, and that confuses some things some
  3226. times, like mail programs and modems.  So, there are encodings of
  3227. MacBinary files as ASCII only files, and one very important one is
  3228. called BinHex4.0.  So far, so good.
  3229. X
  3230. mcvert runs under UNIX and converts between different representations
  3231. of Mac files.  One very common conversion is between BinHex4.0 and
  3232. MacBinary.  So know we know how to do that (on a UNIX box).  On the
  3233. Mac, I prefer the CompactPro shareware for doing this conversion
  3234. X
  3235. A MacBinary file must be converted into the actual native Mac file it
  3236. represents.  One such program, which runs on the Mac, is binhex4.0.
  3237. Often, though, programs like telnet from NCSA, kermit, White Knight,
  3238. or any number of other communication programs will convert MacBinary
  3239. files into the native Mac files they represent during transfer.
  3240. X
  3241. Files can be very large, and rather redundent.  So it makes sense
  3242. to compress the files to save space and reduce transfer cost.
  3243. There are compressed file formats.  Two popular ones are StuffIt
  3244. and CompactPro.  But if a file is compressed, something must
  3245. uncompress it.  There are unstuffers and extractors, which are
  3246. separate programs which work on the compressed files.  Some files
  3247. are "self-extracting", which means the files are actually Mac
  3248. programs which, when run, recreate the original file.
  3249. X
  3250. Files are often identified by extensions, those .ext suffixes at the
  3251. end of the name.  Common suffixes include:
  3252. X
  3253. X    .bin    MacBinary
  3254. X    .sit    StuffIt
  3255. X    .cpt    CompactPro
  3256. X    .hqx    BinHex4.0
  3257. X    .sea    self extracting archive
  3258. X
  3259. It is not uncommon for multiple transformations to be applied, so if
  3260. one had a file called foo.sit.bin, that likely means that it's a
  3261. MacBinary format of a StuffIt archive file.  So, to convert it, you
  3262. must turn the MacBinary file into a native Mac file, and then run
  3263. [un]StuffIt (or CompactPro, which can handle many StuffIt formats).
  3264. X
  3265. There's more information in the info-mac archives about getting files.
  3266. For example, here's info-mac/help/accessing-files.txt, as of 13Jun93:
  3267. X
  3268. >------ Begin Included Message ------
  3269. > To access binaries in the Info-Mac archive at sumex-aim, use your
  3270. > machine's ftp program.  Type "ftp sumex-aim.stanford.edu".  Use the
  3271. > account name "anonymous" (lower-case) and enter any password. Then
  3272. > "cd info-mac" to enter our directory. You should be able to transfer
  3273. > binaries with a statement like "get app/silly-paint.hqx".
  3274. > NOTE: Almost all files (even binaries) in the Info-Mac archive are in
  3275. > text format, even though they may not be human-readable. Hence, a FTP
  3276. > transfer using a text-only option, often called ASCII, should work in
  3277. > all common cases.
  3278. > In order to provide a reasonable level of performance and avoid
  3279. > causing Internet overload, there is a 35-user limit for anonymous ftp
  3280. > into sumex-aim during working hours, which we define as 8AM to 5PM
  3281. > Pacific time, Monday through Friday. When sumex is busy, use one of
  3282. > the many mirror archives around the world (see info/comm/ for a list
  3283. > of other archive sites, including sumex mirrors.) Gopher is another
  3284. > alternative; as a more modern alternative to ftp, it imposes less of a
  3285. > burden on sumex, so there is no user limit.
  3286. > Here are some simple commands to move you around the directory structure.
  3287. > This example assumes that you started in the /info-mac directory.
  3288. >     cd app         # move into the app directory
  3289. >     ls             # list the files there
  3290. >         get planet.hqx # transfer a file to your computer
  3291. >         cd ..          # move back up to the parent directory
  3292. >         cd help        # and so on...
  3293. > Most Info-Mac files are stored in BinHex 4.0 format.  We have adopted
  3294. > the common practice of labeling such files with .hqx extensions.  To
  3295. > take these files and use them on your Macintosh, you must first run
  3296. > them through a program which will convert them from .hqx format into a
  3297. > regular Macintosh file. On Unix systems, you can use the mcvert
  3298. > program, stored as cmp/mcvert.shar. You can also do the conversion on
  3299. > your Macintosh by using any of a number of utilities, including BinHex
  3300. > 4.0, StuffIt, or Compact Pro. We recommend using Compact Pro because
  3301. > it is slightly more convenient and reliable than the other tools.
  3302. > Note: do NOT use BinHex 5.0 as it is incompatible, for some very
  3303. > brain-damaged reasons.
  3304. > Note that some of our files were split into smaller pieces so that
  3305. > they could be mailed more easily.  Most such files are old, as we no
  3306. > longer split new submissions.  You must join split files together
  3307. > before running BinHex or StuffIt. Hqx files can be edited as normal
  3308. > text; therefore, you can use any word processor or append command on
  3309. > your host to stitch the pieces together. There are some utilities
  3310. > (unity and united) in disk/ to do this step for you.
  3311. > Many of our files also have been compressed to save space. You'll know
  3312. > that they have been when the file name after converting to Macintosh
  3313. > format ends with a .sit, .cpt, .sea, or .pit extension. Here is a
  3314. > table to help you with the reconstruction:
  3315. > Extension    Created By    Recommended unpacker    Notes
  3316. > .pit        PackIt II    StuffIt            obsolete format
  3317. > .sit        StuffIt        Compact Pro/StuffIt    has type SIT!
  3318. >         StuffIt Deluxe    Stuffit Expander    has type SITD
  3319. > .cpt        Compact Pro    Compact Pro
  3320. > .sea        various        itself (double-click on it to unpack)
  3321. > In summary, there are generally five steps to pulling .hqx files from our
  3322. > archives:
  3323. >     1. Transfer them to your computer with FTP.
  3324. >     2. Transfer them to your Macintosh somehow.
  3325. >         3. If necessary, put separate pieces together.
  3326. >     4. Run a de-binhexing utility to convert the .hqx files into either
  3327. >            real Macintosh files or compressed Macintosh files.
  3328. >     5. If they are compressed, use the appropriate decompression
  3329. >            program to decompress them.
  3330. > People using Unix may be able to skip steps 3 and 4 by using the program
  3331. > mcvert on their Unix system before transferring the program
  3332. > to their Macintosh.
  3333. > If you don't already have BinHex 4.0, it would be easiest to get it
  3334. > from a friend or user group. Or, if you know how to do an 8-bit binary
  3335. > download, you can FTP it from us as cmp/binhex4.bin. Unfortunately, a
  3336. > little bit of pulling yourself up by the bootstraps is required.
  3337. > StuffIt Expander is a more modern and useful program which incoporates
  3338. > the functionality of Binhex, while also decompressing files. It is
  3339. > also available in cmp/ in both binary and binhexed forms.
  3340. > A CD-ROM of the archives is commercially available from Pacific HiTech.
  3341. > They can be contacted by phone at 800-765-8369,
  3342. > fax at 801-278-2666, and email
  3343. > at 71175.3152@compuserve.com. The CD-ROM is approximately $45 including 
  3344. > shipping and handling.
  3345. > Please note that we cannot test software for reliability on all Macintosh
  3346. > configurations. As the software in this archive is generally non-commercial,
  3347. > it may be less reliable and more prone to crashes than you are used to.
  3348. > We highly recommend that you maintain an active backup procedure to protect
  3349. > yourself even in the event of a system crash that results in the loss of
  3350. > some of your data. Download and use all software in this archive at your own
  3351. > risk.
  3352. > The Info-Mac Moderators
  3353. > info-mac-request@sumex-aim.stanford.edu
  3354. >------  End Included Message  ------
  3355. SHAR_EOF
  3356. chmod 0444 README-conversion ||
  3357. echo 'restore of README-conversion failed'
  3358. Wc_c="`wc -c < 'README-conversion'`"
  3359. test 7655 -eq "$Wc_c" ||
  3360.     echo 'README-conversion: original size 7655, current size' "$Wc_c"
  3361. fi
  3362. # ============= mcvert.idraw ==============
  3363. if test -f 'mcvert.idraw' -a X"$1" != X"-c"; then
  3364.     echo 'x - skipping mcvert.idraw (File already exists)'
  3365. else
  3366. echo 'x - extracting mcvert.idraw (Text)'
  3367. sed 's/^X//' << 'SHAR_EOF' > 'mcvert.idraw' &&
  3368. %!PS-Adobe-2.0 EPSF-1.2
  3369. %%DocumentFonts: Helvetica-Bold
  3370. %%Pages: 1
  3371. %%BoundingBox: 69 66 547 688
  3372. %%EndComments
  3373. X
  3374. %% Contributed by
  3375. %% Brian Bartholomew - bb@math.ufl.edu - Univ. of Florida Dept. of Mathematics
  3376. %% Sat, 20 Feb 93 04:45:04 EST
  3377. X
  3378. 50 dict begin
  3379. X
  3380. /arrowHeight 8 def
  3381. /arrowWidth 4 def
  3382. /none null def
  3383. /numGraphicParameters 17 def
  3384. /stringLimit 65535 def
  3385. X
  3386. /Begin {
  3387. save
  3388. numGraphicParameters dict begin
  3389. } def
  3390. X
  3391. /End {
  3392. end
  3393. restore
  3394. } def
  3395. X
  3396. /SetB {
  3397. dup type /nulltype eq {
  3398. pop
  3399. false /brushRightArrow idef
  3400. false /brushLeftArrow idef
  3401. true /brushNone idef
  3402. } {
  3403. /brushDashOffset idef
  3404. /brushDashArray idef
  3405. 0 ne /brushRightArrow idef
  3406. 0 ne /brushLeftArrow idef
  3407. /brushWidth idef
  3408. false /brushNone idef
  3409. } ifelse
  3410. } def
  3411. X
  3412. /SetCFg {
  3413. /fgblue idef
  3414. /fggreen idef
  3415. /fgred idef
  3416. } def
  3417. X
  3418. /SetCBg {
  3419. /bgblue idef
  3420. /bggreen idef
  3421. /bgred idef
  3422. } def
  3423. X
  3424. /SetF {
  3425. /printSize idef
  3426. /printFont idef
  3427. } def
  3428. X
  3429. /SetP {
  3430. dup type /nulltype eq {
  3431. pop true /patternNone idef
  3432. } {
  3433. dup -1 eq {
  3434. /patternGrayLevel idef
  3435. /patternString idef
  3436. } {
  3437. /patternGrayLevel idef
  3438. } ifelse
  3439. false /patternNone idef
  3440. } ifelse
  3441. } def
  3442. X
  3443. /BSpl {
  3444. 0 begin
  3445. storexyn
  3446. newpath
  3447. n 1 gt {
  3448. 0 0 0 0 0 0 1 1 true subspline
  3449. n 2 gt {
  3450. 0 0 0 0 1 1 2 2 false subspline
  3451. 1 1 n 3 sub {
  3452. /i exch def
  3453. i 1 sub dup i dup i 1 add dup i 2 add dup false subspline
  3454. } for
  3455. n 3 sub dup n 2 sub dup n 1 sub dup 2 copy false subspline
  3456. } if
  3457. n 2 sub dup n 1 sub dup 2 copy 2 copy false subspline
  3458. patternNone not brushLeftArrow not brushRightArrow not and and { ifill } if
  3459. brushNone not { istroke } if
  3460. 0 0 1 1 leftarrow
  3461. n 2 sub dup n 1 sub dup rightarrow
  3462. } if
  3463. end
  3464. } dup 0 4 dict put def
  3465. X
  3466. /Circ {
  3467. newpath
  3468. 0 360 arc
  3469. patternNone not { ifill } if
  3470. brushNone not { istroke } if
  3471. } def
  3472. X
  3473. /CBSpl {
  3474. 0 begin
  3475. dup 2 gt {
  3476. storexyn
  3477. newpath
  3478. n 1 sub dup 0 0 1 1 2 2 true subspline
  3479. 1 1 n 3 sub {
  3480. /i exch def
  3481. i 1 sub dup i dup i 1 add dup i 2 add dup false subspline
  3482. } for
  3483. n 3 sub dup n 2 sub dup n 1 sub dup 0 0 false subspline
  3484. n 2 sub dup n 1 sub dup 0 0 1 1 false subspline
  3485. patternNone not { ifill } if
  3486. brushNone not { istroke } if
  3487. } {
  3488. Poly
  3489. } ifelse
  3490. end
  3491. } dup 0 4 dict put def
  3492. X
  3493. /Elli {
  3494. 0 begin
  3495. newpath
  3496. 4 2 roll
  3497. translate
  3498. scale
  3499. 0 0 1 0 360 arc
  3500. patternNone not { ifill } if
  3501. brushNone not { istroke } if
  3502. end
  3503. } dup 0 1 dict put def
  3504. X
  3505. /Line {
  3506. 0 begin
  3507. 2 storexyn
  3508. newpath
  3509. x 0 get y 0 get moveto
  3510. x 1 get y 1 get lineto
  3511. brushNone not { istroke } if
  3512. 0 0 1 1 leftarrow
  3513. 0 0 1 1 rightarrow
  3514. end
  3515. } dup 0 4 dict put def
  3516. X
  3517. /MLine {
  3518. 0 begin
  3519. storexyn
  3520. newpath
  3521. n 1 gt {
  3522. x 0 get y 0 get moveto
  3523. 1 1 n 1 sub {
  3524. /i exch def
  3525. x i get y i get lineto
  3526. } for
  3527. patternNone not brushLeftArrow not brushRightArrow not and and { ifill } if
  3528. brushNone not { istroke } if
  3529. 0 0 1 1 leftarrow
  3530. n 2 sub dup n 1 sub dup rightarrow
  3531. } if
  3532. end
  3533. } dup 0 4 dict put def
  3534. X
  3535. /Poly {
  3536. 3 1 roll
  3537. newpath
  3538. moveto
  3539. -1 add
  3540. { lineto } repeat
  3541. closepath
  3542. patternNone not { ifill } if
  3543. brushNone not { istroke } if
  3544. } def
  3545. X
  3546. /Rect {
  3547. 0 begin
  3548. /t exch def
  3549. /r exch def
  3550. /b exch def
  3551. /l exch def
  3552. newpath
  3553. l b moveto
  3554. l t lineto
  3555. r t lineto
  3556. r b lineto
  3557. closepath
  3558. patternNone not { ifill } if
  3559. brushNone not { istroke } if
  3560. end
  3561. } dup 0 4 dict put def
  3562. X
  3563. /Text {
  3564. ishow
  3565. } def
  3566. X
  3567. /idef {
  3568. dup where { pop pop pop } { exch def } ifelse
  3569. } def
  3570. X
  3571. /ifill {
  3572. 0 begin
  3573. gsave
  3574. patternGrayLevel -1 ne {
  3575. fgred bgred fgred sub patternGrayLevel mul add
  3576. fggreen bggreen fggreen sub patternGrayLevel mul add
  3577. fgblue bgblue fgblue sub patternGrayLevel mul add setrgbcolor
  3578. eofill
  3579. } {
  3580. eoclip
  3581. originalCTM setmatrix
  3582. pathbbox /t exch def /r exch def /b exch def /l exch def
  3583. /w r l sub ceiling cvi def
  3584. /h t b sub ceiling cvi def
  3585. /imageByteWidth w 8 div ceiling cvi def
  3586. /imageHeight h def
  3587. bgred bggreen bgblue setrgbcolor
  3588. eofill
  3589. fgred fggreen fgblue setrgbcolor
  3590. w 0 gt h 0 gt and {
  3591. l b translate w h scale
  3592. w h true [w 0 0 h neg 0 h] { patternproc } imagemask
  3593. } if
  3594. } ifelse
  3595. grestore
  3596. end
  3597. } dup 0 8 dict put def
  3598. X
  3599. /istroke {
  3600. gsave
  3601. brushDashOffset -1 eq {
  3602. [] 0 setdash
  3603. 1 setgray
  3604. } {
  3605. brushDashArray brushDashOffset setdash
  3606. fgred fggreen fgblue setrgbcolor
  3607. } ifelse
  3608. brushWidth setlinewidth
  3609. originalCTM setmatrix
  3610. stroke
  3611. grestore
  3612. } def
  3613. X
  3614. /ishow {
  3615. 0 begin
  3616. gsave
  3617. fgred fggreen fgblue setrgbcolor
  3618. /fontDict printFont findfont printSize scalefont dup setfont def
  3619. /descender fontDict begin 0 [FontBBox] 1 get FontMatrix end
  3620. transform exch pop def
  3621. /vertoffset 0 descender sub printSize sub printFont /Courier ne
  3622. printFont /Courier-Bold ne and { 1 add } if def {
  3623. 0 vertoffset moveto show
  3624. /vertoffset vertoffset printSize sub def
  3625. } forall
  3626. grestore
  3627. end
  3628. } dup 0 3 dict put def
  3629. X
  3630. /patternproc {
  3631. 0 begin
  3632. /patternByteLength patternString length def
  3633. /patternHeight patternByteLength 8 mul sqrt cvi def
  3634. /patternWidth patternHeight def
  3635. /patternByteWidth patternWidth 8 idiv def
  3636. /imageByteMaxLength imageByteWidth imageHeight mul
  3637. stringLimit patternByteWidth sub min def
  3638. /imageMaxHeight imageByteMaxLength imageByteWidth idiv patternHeight idiv
  3639. patternHeight mul patternHeight max def
  3640. /imageHeight imageHeight imageMaxHeight sub store
  3641. /imageString imageByteWidth imageMaxHeight mul patternByteWidth add string def
  3642. 0 1 imageMaxHeight 1 sub {
  3643. /y exch def
  3644. /patternRow y patternByteWidth mul patternByteLength mod def
  3645. /patternRowString patternString patternRow patternByteWidth getinterval def
  3646. /imageRow y imageByteWidth mul def
  3647. 0 patternByteWidth imageByteWidth 1 sub {
  3648. /x exch def
  3649. imageString imageRow x add patternRowString putinterval
  3650. } for
  3651. } for
  3652. imageString
  3653. end
  3654. } dup 0 12 dict put def
  3655. X
  3656. /min {
  3657. dup 3 2 roll dup 4 3 roll lt { exch } if pop
  3658. } def
  3659. X
  3660. /max {
  3661. dup 3 2 roll dup 4 3 roll gt { exch } if pop
  3662. } def
  3663. X
  3664. /arrowhead {
  3665. 0 begin
  3666. transform originalCTM itransform
  3667. /taily exch def
  3668. /tailx exch def
  3669. transform originalCTM itransform
  3670. /tipy exch def
  3671. /tipx exch def
  3672. /dy tipy taily sub def
  3673. /dx tipx tailx sub def
  3674. /angle dx 0 ne dy 0 ne or { dy dx atan } { 90 } ifelse def
  3675. gsave
  3676. originalCTM setmatrix
  3677. tipx tipy translate
  3678. angle rotate
  3679. newpath
  3680. 0 0 moveto
  3681. arrowHeight neg arrowWidth 2 div lineto
  3682. arrowHeight neg arrowWidth 2 div neg lineto
  3683. closepath
  3684. patternNone not {
  3685. originalCTM setmatrix
  3686. /padtip arrowHeight 2 exp 0.25 arrowWidth 2 exp mul add sqrt brushWidth mul
  3687. arrowWidth div def
  3688. /padtail brushWidth 2 div def
  3689. tipx tipy translate
  3690. angle rotate
  3691. padtip 0 translate
  3692. arrowHeight padtip add padtail add arrowHeight div dup scale
  3693. arrowheadpath
  3694. ifill
  3695. } if
  3696. brushNone not {
  3697. originalCTM setmatrix
  3698. tipx tipy translate
  3699. angle rotate
  3700. arrowheadpath
  3701. istroke
  3702. } if
  3703. grestore
  3704. end
  3705. } dup 0 9 dict put def
  3706. X
  3707. /arrowheadpath {
  3708. newpath
  3709. 0 0 moveto
  3710. arrowHeight neg arrowWidth 2 div lineto
  3711. arrowHeight neg arrowWidth 2 div neg lineto
  3712. closepath
  3713. } def
  3714. X
  3715. /leftarrow {
  3716. 0 begin
  3717. y exch get /taily exch def
  3718. x exch get /tailx exch def
  3719. y exch get /tipy exch def
  3720. x exch get /tipx exch def
  3721. brushLeftArrow { tipx tipy tailx taily arrowhead } if
  3722. end
  3723. } dup 0 4 dict put def
  3724. X
  3725. /rightarrow {
  3726. 0 begin
  3727. y exch get /tipy exch def
  3728. x exch get /tipx exch def
  3729. y exch get /taily exch def
  3730. x exch get /tailx exch def
  3731. brushRightArrow { tipx tipy tailx taily arrowhead } if
  3732. end
  3733. } dup 0 4 dict put def
  3734. X
  3735. /midpoint {
  3736. 0 begin
  3737. /y1 exch def
  3738. /x1 exch def
  3739. /y0 exch def
  3740. /x0 exch def
  3741. x0 x1 add 2 div
  3742. y0 y1 add 2 div
  3743. end
  3744. } dup 0 4 dict put def
  3745. X
  3746. /thirdpoint {
  3747. 0 begin
  3748. /y1 exch def
  3749. /x1 exch def
  3750. /y0 exch def
  3751. /x0 exch def
  3752. x0 2 mul x1 add 3 div
  3753. y0 2 mul y1 add 3 div
  3754. end
  3755. } dup 0 4 dict put def
  3756. X
  3757. /subspline {
  3758. 0 begin
  3759. /movetoNeeded exch def
  3760. y exch get /y3 exch def
  3761. x exch get /x3 exch def
  3762. y exch get /y2 exch def
  3763. x exch get /x2 exch def
  3764. y exch get /y1 exch def
  3765. x exch get /x1 exch def
  3766. y exch get /y0 exch def
  3767. x exch get /x0 exch def
  3768. x1 y1 x2 y2 thirdpoint
  3769. /p1y exch def
  3770. /p1x exch def
  3771. x2 y2 x1 y1 thirdpoint
  3772. /p2y exch def
  3773. /p2x exch def
  3774. x1 y1 x0 y0 thirdpoint
  3775. p1x p1y midpoint
  3776. /p0y exch def
  3777. /p0x exch def
  3778. x2 y2 x3 y3 thirdpoint
  3779. p2x p2y midpoint
  3780. /p3y exch def
  3781. /p3x exch def
  3782. movetoNeeded { p0x p0y moveto } if
  3783. p1x p1y p2x p2y p3x p3y curveto
  3784. end
  3785. } dup 0 17 dict put def
  3786. X
  3787. /storexyn {
  3788. /n exch def
  3789. /y n array def
  3790. /x n array def
  3791. n 1 sub -1 0 {
  3792. /i exch def
  3793. y i 3 2 roll put
  3794. x i 3 2 roll put
  3795. } for
  3796. } def
  3797. X
  3798. %%EndProlog
  3799. X
  3800. %I Idraw 7 Grid 8 
  3801. X
  3802. %%Page: 1 1
  3803. X
  3804. Begin
  3805. %I b u
  3806. %I cfg u
  3807. %I cbg u
  3808. %I f u
  3809. %I p u
  3810. %I t
  3811. [ 0.8 0 0 0.8 0 0 ] concat
  3812. /originalCTM matrix currentmatrix def
  3813. X
  3814. Begin %I Rect
  3815. %I b 65535
  3816. 2 0 0 [] 0 SetB
  3817. %I cfg Black
  3818. 0 0 0 SetCFg
  3819. %I cbg White
  3820. 1 1 1 SetCBg
  3821. none SetP %I p n
  3822. %I t
  3823. [ 1 0 0 1 -72 275 ] concat
  3824. %I
  3825. 361 198 556 269 Rect
  3826. End
  3827. X
  3828. Begin %I Rect
  3829. %I b 65535
  3830. 2 0 0 [] 0 SetB
  3831. %I cfg Black
  3832. 0 0 0 SetCFg
  3833. %I cbg White
  3834. 1 1 1 SetCBg
  3835. none SetP %I p n
  3836. %I t
  3837. [ 1 0 0 1 -271 479 ] concat
  3838. %I
  3839. 361 198 556 269 Rect
  3840. End
  3841. X
  3842. Begin %I Rect
  3843. %I b 65535
  3844. 2 0 0 [] 0 SetB
  3845. %I cfg Black
  3846. 0 0 0 SetCFg
  3847. %I cbg White
  3848. 1 1 1 SetCBg
  3849. none SetP %I p n
  3850. %I t
  3851. [ 1 0 0 1 97 486 ] concat
  3852. %I
  3853. 361 198 556 269 Rect
  3854. End
  3855. X
  3856. Begin %I Rect
  3857. %I b 65535
  3858. 2 0 0 [] 0 SetB
  3859. %I cfg Black
  3860. 0 0 0 SetCFg
  3861. %I cbg White
  3862. 1 1 1 SetCBg
  3863. none SetP %I p n
  3864. %I t
  3865. [ 1 0 0 1 125 81 ] concat
  3866. %I
  3867. 361 198 556 269 Rect
  3868. End
  3869. X
  3870. Begin %I Rect
  3871. %I b 65535
  3872. 2 0 0 [] 0 SetB
  3873. %I cfg Black
  3874. 0 0 0 SetCFg
  3875. %I cbg White
  3876. 1 1 1 SetCBg
  3877. none SetP %I p n
  3878. %I t
  3879. [ 1 0 0 1 -269 85 ] concat
  3880. %I
  3881. 361 198 556 269 Rect
  3882. End
  3883. X
  3884. Begin %I Text
  3885. %I cfg Black
  3886. 0 0 0 SetCFg
  3887. %I f *-helvetica-bold-r-*-140-*
  3888. /Helvetica-Bold 14 SetF
  3889. %I t
  3890. [ 1 0 0 1 348 513 ] concat
  3891. %I
  3892. [
  3893. (MacBinary)
  3894. ] Text
  3895. End
  3896. X
  3897. Begin %I Text
  3898. %I cfg Black
  3899. 0 0 0 SetCFg
  3900. %I f *-helvetica-bold-r-*-140-*
  3901. /Helvetica-Bold 14 SetF
  3902. %I t
  3903. [ 1 0 0 1 513 723 ] concat
  3904. %I
  3905. [
  3906. (BinHex 4.0)
  3907. ] Text
  3908. End
  3909. X
  3910. Begin %I Text
  3911. %I cfg Black
  3912. 0 0 0 SetCFg
  3913. %I f *-helvetica-bold-r-*-140-*
  3914. /Helvetica-Bold 14 SetF
  3915. %I t
  3916. [ 1 0 0 1 150 324 ] concat
  3917. %I
  3918. [
  3919. (Data Fork)
  3920. ] Text
  3921. End
  3922. X
  3923. Begin %I Text
  3924. %I cfg Black
  3925. 0 0 0 SetCFg
  3926. %I f *-helvetica-bold-r-*-140-*
  3927. /Helvetica-Bold 14 SetF
  3928. %I t
  3929. [ 1 0 0 1 534 322 ] concat
  3930. %I
  3931. [
  3932. (Resource Fork)
  3933. ] Text
  3934. End
  3935. X
  3936. Begin %I Text
  3937. %I cfg Black
  3938. 0 0 0 SetCFg
  3939. %I f *-helvetica-bold-r-*-140-*
  3940. /Helvetica-Bold 14 SetF
  3941. %I t
  3942. [ 1 0 0 1 173 717 ] concat
  3943. %I
  3944. [
  3945. (Text)
  3946. ] Text
  3947. End
  3948. X
  3949. Begin %I Line
  3950. %I b 65535
  3951. 1 1 0 [] 0 SetB
  3952. %I cfg Black
  3953. 0 0 0 SetCFg
  3954. %I cbg White
  3955. 1 1 1 SetCBg
  3956. %I p
  3957. 0 SetP
  3958. %I t
  3959. [ 1 0 0 1 -89 166 ] concat
  3960. %I
  3961. 287 500 373 393 Line
  3962. End
  3963. X
  3964. Begin %I Line
  3965. %I b 65535
  3966. 1 0 1 [] 0 SetB
  3967. %I cfg Black
  3968. 0 0 0 SetCFg
  3969. %I cbg White
  3970. 1 1 1 SetCBg
  3971. %I p
  3972. 0 SetP
  3973. %I t
  3974. [ 1 0 0 1 -69 167 ] concat
  3975. %I
  3976. 355 286 310 199 Line
  3977. End
  3978. X
  3979. Begin %I Line
  3980. %I b 65535
  3981. 1 0 1 [] 0 SetB
  3982. %I cfg Black
  3983. 0 0 0 SetCFg
  3984. %I cbg White
  3985. 1 1 1 SetCBg
  3986. %I p
  3987. 0 SetP
  3988. %I t
  3989. [ 1 0 0 1 -69 167 ] concat
  3990. %I
  3991. 547 290 609 198 Line
  3992. End
  3993. X
  3994. Begin %I Line
  3995. %I b 65535
  3996. 1 0 1 [] 0 SetB
  3997. %I cfg Black
  3998. 0 0 0 SetCFg
  3999. %I cbg White
  4000. 1 1 1 SetCBg
  4001. %I p
  4002. 0 SetP
  4003. %I t
  4004. [ 1 0 0 1 -69 167 ] concat
  4005. %I
  4006. 542 395 584 504 Line
  4007. End
  4008. X
  4009. Begin %I Line
  4010. %I b 65535
  4011. 1 1 0 [] 0 SetB
  4012. %I cfg Black
  4013. 0 0 0 SetCFg
  4014. %I cbg White
  4015. 1 1 1 SetCBg
  4016. %I p
  4017. 0 SetP
  4018. %I t
  4019. [ 1 0 0 1 -44 162 ] concat
  4020. %I
  4021. 542 395 584 504 Line
  4022. End
  4023. X
  4024. Begin %I Line
  4025. %I b 65535
  4026. 1 0 1 [] 0 SetB
  4027. %I cfg Black
  4028. 0 0 0 SetCFg
  4029. %I cbg White
  4030. 1 1 1 SetCBg
  4031. %I p
  4032. 0 SetP
  4033. %I t
  4034. [ 1 0 0 1 -58 170 ] concat
  4035. %I
  4036. 287 500 373 393 Line
  4037. End
  4038. X
  4039. Begin %I Line
  4040. %I b 65535
  4041. 1 1 0 [] 0 SetB
  4042. %I cfg Black
  4043. 0 0 0 SetCFg
  4044. %I cbg White
  4045. 1 1 1 SetCBg
  4046. %I p
  4047. 0 SetP
  4048. %I t
  4049. [ 1 0 0 1 -40 167 ] concat
  4050. %I
  4051. 355 286 310 199 Line
  4052. End
  4053. X
  4054. Begin %I Line
  4055. %I b 65535
  4056. 1 1 0 [] 0 SetB
  4057. %I cfg Black
  4058. 0 0 0 SetCFg
  4059. %I cbg White
  4060. 1 1 1 SetCBg
  4061. %I p
  4062. 0 SetP
  4063. %I t
  4064. [ 1 0 0 1 -43 176 ] concat
  4065. %I
  4066. 547 290 609 198 Line
  4067. End
  4068. X
  4069. Begin %I Text
  4070. %I cfg Black
  4071. 0 0 0 SetCFg
  4072. %I f *-helvetica-bold-r-*-140-*
  4073. /Helvetica-Bold 14 SetF
  4074. %I t
  4075. [ 1 0 0 1 224 419 ] concat
  4076. %I
  4077. [
  4078. (-dU)
  4079. ] Text
  4080. End
  4081. X
  4082. Begin %I Text
  4083. %I cfg Black
  4084. 0 0 0 SetCFg
  4085. %I f *-helvetica-bold-r-*-140-*
  4086. /Helvetica-Bold 14 SetF
  4087. %I t
  4088. [ 1 0 0 1 304 406 ] concat
  4089. %I
  4090. [
  4091. (-dD)
  4092. ] Text
  4093. End
  4094. X
  4095. Begin %I Text
  4096. %I cfg Black
  4097. 0 0 0 SetCFg
  4098. %I f *-helvetica-bold-r-*-140-*
  4099. /Helvetica-Bold 14 SetF
  4100. %I t
  4101. [ 1 0 0 1 467 405 ] concat
  4102. %I
  4103. [
  4104. (-rU)
  4105. ] Text
  4106. End
  4107. X
  4108. Begin %I Text
  4109. %I cfg Black
  4110. 0 0 0 SetCFg
  4111. %I f *-helvetica-bold-r-*-140-*
  4112. /Helvetica-Bold 14 SetF
  4113. %I t
  4114. [ 1 0 0 1 553 429 ] concat
  4115. %I
  4116. [
  4117. (-rD)
  4118. ] Text
  4119. End
  4120. X
  4121. Begin %I Text
  4122. %I cfg Black
  4123. 0 0 0 SetCFg
  4124. %I f *-helvetica-bold-r-*-140-*
  4125. /Helvetica-Bold 14 SetF
  4126. %I t
  4127. [ 1 0 0 1 458 629 ] concat
  4128. %I
  4129. [
  4130. (-xU)
  4131. ] Text
  4132. End
  4133. X
  4134. Begin %I Text
  4135. %I cfg Black
  4136. 0 0 0 SetCFg
  4137. %I f *-helvetica-bold-r-*-140-*
  4138. /Helvetica-Bold 14 SetF
  4139. %I t
  4140. [ 1 0 0 1 536 613 ] concat
  4141. %I
  4142. [
  4143. (-xD)
  4144. ] Text
  4145. End
  4146. X
  4147. Begin %I Text
  4148. %I cfg Black
  4149. 0 0 0 SetCFg
  4150. %I f *-helvetica-bold-r-*-140-*
  4151. /Helvetica-Bold 14 SetF
  4152. %I t
  4153. [ 1 0 0 1 284 631 ] concat
  4154. %I
  4155. [
  4156. (-uD)
  4157. ] Text
  4158. End
  4159. X
  4160. Begin %I Text
  4161. %I cfg Black
  4162. 0 0 0 SetCFg
  4163. %I f *-helvetica-bold-r-*-140-*
  4164. /Helvetica-Bold 14 SetF
  4165. %I t
  4166. [ 1 0 0 1 199 611 ] concat
  4167. %I
  4168. [
  4169. (-uU)
  4170. ] Text
  4171. End
  4172. X
  4173. Begin %I Text
  4174. %I cfg Black
  4175. 0 0 0 SetCFg
  4176. %I f *-helvetica-bold-r-*-140-*
  4177. /Helvetica-Bold 14 SetF
  4178. %I t
  4179. [ 1 0 0 1 451 536 ] concat
  4180. %I
  4181. [
  4182. (.bin)
  4183. ] Text
  4184. End
  4185. X
  4186. Begin %I Text
  4187. %I cfg Black
  4188. 0 0 0 SetCFg
  4189. %I f *-helvetica-bold-r-*-140-*
  4190. /Helvetica-Bold 14 SetF
  4191. %I t
  4192. [ 1 0 0 1 619 748 ] concat
  4193. %I
  4194. [
  4195. (.hqx)
  4196. ] Text
  4197. End
  4198. X
  4199. Begin %I Text
  4200. %I cfg Black
  4201. 0 0 0 SetCFg
  4202. %I f *-helvetica-bold-r-*-140-*
  4203. /Helvetica-Bold 14 SetF
  4204. %I t
  4205. [ 1 0 0 1 274 150 ] concat
  4206. %I
  4207. [
  4208. (-s  Silent)
  4209. ] Text
  4210. End
  4211. X
  4212. Begin %I Text
  4213. %I cfg Black
  4214. 0 0 0 SetCFg
  4215. %I f *-helvetica-bold-r-*-140-*
  4216. /Helvetica-Bold 14 SetF
  4217. %I t
  4218. [ 1 0 0 1 274 125 ] concat
  4219. %I
  4220. [
  4221. (-v  Verbose)
  4222. ] Text
  4223. End
  4224. X
  4225. Begin %I Text
  4226. %I cfg Black
  4227. 0 0 0 SetCFg
  4228. %I f *-helvetica-bold-r-*-140-*
  4229. /Helvetica-Bold 14 SetF
  4230. %I t
  4231. [ 2.24324 0 0 2.24324 244 850.216 ] concat
  4232. %I
  4233. [
  4234. (mcvert\(1\) options)
  4235. ] Text
  4236. End
  4237. X
  4238. Begin %I Text
  4239. %I cfg Black
  4240. 0 0 0 SetCFg
  4241. %I f *-helvetica-bold-r-*-140-*
  4242. /Helvetica-Bold 14 SetF
  4243. %I t
  4244. [ 1 0 0 1 274 100 ] concat
  4245. %I
  4246. [
  4247. (-p  Unpack top-level PackIt archives)
  4248. ] Text
  4249. End
  4250. X
  4251. End %I eop
  4252. X
  4253. showpage
  4254. X
  4255. %%Trailer
  4256. X
  4257. end
  4258. SHAR_EOF
  4259. chmod 0444 mcvert.idraw ||
  4260. echo 'restore of mcvert.idraw failed'
  4261. Wc_c="`wc -c < 'mcvert.idraw'`"
  4262. test 13179 -eq "$Wc_c" ||
  4263.     echo 'mcvert.idraw: original size 13179, current size' "$Wc_c"
  4264. fi
  4265. # ============= mcvert.1 ==============
  4266. if test -f 'mcvert.1' -a X"$1" != X"-c"; then
  4267.     echo 'x - skipping mcvert.1 (File already exists)'
  4268. else
  4269. echo 'x - extracting mcvert.1 (Text)'
  4270. sed 's/^X//' << 'SHAR_EOF' > 'mcvert.1' &&
  4271. .TH MCVERT LOCAL "10Nov93"
  4272. .UC 4.2
  4273. .SH NAME
  4274. mcvert \- MacBinary <=> BinHex 4.0 and more file conversion utility
  4275. .SH SYNOPSIS
  4276. .B mcvert
  4277. { [option] ... name ... } ...
  4278. .br
  4279. .SH DESCRIPTION
  4280. The
  4281. .I mcvert
  4282. program translates files between MacBinary format and
  4283. other formats often used in exchanging Macintosh files.
  4284. See
  4285. .I FILE FORMATS
  4286. below for a description of the file formats supported.
  4287. .SH PARAMETERS
  4288. The defaults for the parameters are
  4289. .RB - xDqv :
  4290. convert BinHex 4.0 files
  4291. .RB ( x )
  4292. to MacBinary files
  4293. .RB ( D ),
  4294. bypass automatic unpacking of PIT files
  4295. .RB ( q ),
  4296. and provide a verbose level of output
  4297. .RB ( v ).
  4298. .SH "OPTIONS"
  4299. All the options, other than
  4300. .I "FORMAT OPTIONS"
  4301. described below, are listed here.
  4302. XFrom each set, one and only one alternative is active for any one file.
  4303. .TP
  4304. .B U | D
  4305. When option -U, as in Upload, is selected,
  4306. the conversion is from MacBinary to something else.
  4307. Conversely, option -D, as in Download,
  4308. selects conversion from something to MacBinary.
  4309. .TP
  4310. .B p | q
  4311. If a BinHex 4.0 to MacBinary conversion is taking place
  4312. and option -p, as in Pit, is selected,
  4313. any file of type "PIT "
  4314. will be unpacked into its constituent parts.
  4315. This option does not recursively
  4316. unpack "PIT " files packed in "PIT " files.
  4317. If a MacBinary to BinHex 4.0 conversion is taking place,
  4318. this option is currently
  4319. ignored.
  4320. Conversely, option -q, as in Quiescent, does no such unpacking.
  4321. .TP
  4322. .B t
  4323. Macintosh and UNIX differ in the end-of-line character they use.
  4324. Option -t, as in Translate,
  4325. enables end-of-line character translation for the data.
  4326. Translation is off by default,
  4327. but it is enabled automatically when processing -u (Usual Text) files.
  4328. Option -t is useful when processing both data and resource files at the
  4329. same time (option -b) to enable end-of-line character translation for
  4330. the data.
  4331. .TP
  4332. .B
  4333. S | s | v | V | VV
  4334. Normally,
  4335. .I mcvert
  4336. prints converting messages and other information
  4337. about the files it is processing to stderr.
  4338. Option -S, as in SILENT, disables all such reporting.
  4339. Option -s, as in Silent, disables all but the "Converting ..." messages.
  4340. Option -v, as in Verbose, emits generally useful information.
  4341. Option -V, as in VERBOSE, displays some additional debugging information.
  4342. Option -VV, as in VERY VERBOSE, 
  4343. displays detailed debugging information as well.
  4344. .TP
  4345. .B H
  4346. Option -H, as in Heuristic,
  4347. disables the skip-legal-but-suspect-lines heuristic
  4348. used when processing BinHex 4.0 formatted input files.
  4349. See
  4350. .I BUGS
  4351. below for details on the heuristic.
  4352. .TP
  4353. .B I
  4354. Option -I, as in Information only,
  4355. does not write output files, but does indicate which output files would
  4356. normally be written.
  4357. All other operations are performed, including verifying file formats
  4358. and calculated CRC values.
  4359. The -I option basically provides a non-destructive verification of the
  4360. files and their processing.
  4361. It is also a soothing balm for the
  4362. somewhat paranoid, since it reports what files would be changed,
  4363. without actually changing them.
  4364. .TP
  4365. .B P
  4366. Option -P, as in Pipe output to stdout,
  4367. writes the resulting output file(s) to stdout,
  4368. rather than
  4369. to the file system
  4370. with the appropriate extension.
  4371. The default is to use the file system.
  4372. .SH "FILE FORMATS"
  4373. Some useful formats in which Macintosh files are represented on non-Macs are:
  4374. .TP
  4375. .B MacBinary:
  4376. An eight bit wide representation of the data and resource forks of a Mac
  4377. file and of relevant Finder information, MacBinary files are recognized
  4378. as "special" by several Macintosh terminal emulators.  These emulators,
  4379. using kermit or xmodem or other file transfer protocols,
  4380. can separate
  4381. the incoming file into forks and appropriately modify the Desktop to display
  4382. icons, types, creation dates, and the like.
  4383. .TP
  4384. .B BinHex 4.0:
  4385. A seven bit wide representation of a Mac file with CRC error checking,
  4386. BinHex 4.0 files are designed for communication of Mac files over long
  4387. distance, possibly noisy, seven bit wide paths.
  4388. .TP
  4389. .B PackIt:
  4390. PackIt files are actually representations of collections of Mac files, possibly
  4391. Huffman compressed.  Packing many small related files together before
  4392. a MacBinary transfer or a translation to BinHex 4.0 is common practice.
  4393. .TP
  4394. .B Text:
  4395. A Macintosh ends each line of a plain text file with a carriage return
  4396. character (^M), rather than the newline character (^J) that some systems
  4397. require (for example, UNIX).
  4398. Moreover, a MacBinary file has prepended Finder information
  4399. that non-Macintoshes usually don't expect.
  4400. .TP
  4401. .B Data, Rsrc:
  4402. A Data or Rsrc file is the exact copy of the data or resource fork of a
  4403. Macintosh file.
  4404. .SH "FORMAT OPTIONS"
  4405. Exactly one of the following selections may be specified for an input name:
  4406. .TP
  4407. .B x
  4408. BinHex 4.0 [.hqx] - files in the MacBinary format are translated to
  4409. BinHex 4.0 files, or vice versa.
  4410. The name argument is the name of a file to be converted.
  4411. If the conversion is from BinHex 4.0 to MacBinary,
  4412. several files may comprise the BinHex 4.0 representation of the Mac file.
  4413. Rather than manually concatenate the files and manually delete mail
  4414. headers and other extraneous garbage, one may specify the names of the
  4415. files in order and
  4416. .I mcvert
  4417. will do the concatenating and deleting.  Conversely, in converting
  4418. a MacBinary file to BinHex 4.0 format for mailing over long distances,
  4419. one may be restricted to mail messages of no greater that some fixed
  4420. length.  In this case,
  4421. .I mcvert
  4422. can automatically divide the BinHex 4.0 file into pieces and label each
  4423. piece appropriately.
  4424. For details on automatically segmenting files, see the description of the
  4425. .B MAC_LINE_LIMIT
  4426. environment variable below.
  4427. .TP
  4428. .B u | h
  4429. Text [.text] - files in the MacBinary format with nonempty data forks
  4430. and empty resource forks are made from ordinary data files, or vice versa.
  4431. Option -u, for Usual Text, performs translation.
  4432. Option -h, for Host Text, performs no translation.
  4433. When translating,
  4434. UNIX newline
  4435. characters are interchanged with Macintosh carriage return
  4436. characters.
  4437. .TP
  4438. .B d
  4439. Data [.data] - files in the MacBinary format with nonempty data forks
  4440. and empty resource forks are made from ordinary data files, or vice
  4441. versa.  If the data is really text, you should use -u or -h so that
  4442. the file type and creator get set correctly.
  4443. .TP
  4444. .B r
  4445. Resource [.rsrc] - files in the MacBinary format with empty data forks
  4446. and nonempty resource forks are made from ordinary data files, or vice versa.
  4447. .TP
  4448. .B b
  4449. Both [.data .rsrc] -
  4450. files in the MacBinary format with nonempty data forks and
  4451. and nonempty resource forks are made from ordinary data files, or vice versa.
  4452. For option -b processing, a single base file name is provided, and
  4453. the ".data" and ".rsrc" extensions are supplied by
  4454. .IR mcvert .
  4455. .SH "FILE NAMES AND EXTENSIONS"
  4456. .PP
  4457. .I mcvert
  4458. uses certain
  4459. file extensions when reading and writing files.  These
  4460. extensions are indicated in the "FORMAT OPTIONS" section above.
  4461. For example, the appropriate extension for a BinHex 4.0 file is
  4462. ".hqx".
  4463. .PP
  4464. For input files,
  4465. .I mcvert 
  4466. first tries to open the file using the specified name.
  4467. If that fails,
  4468. .I mcvert
  4469. appends the appropriate suffix (if not already present) and tries again.
  4470. Recall that for option -b (Both) processing,
  4471. a single base file name must be provided, since
  4472. the ".data" and ".rsrc" extensions are appended automatically by
  4473. .IR mcvert .
  4474. For example,
  4475. "mcvert foo" will try to open "foo",
  4476. and failing that, try to open "foo.hqx" for input;
  4477. while "mcvert -b foo" will open only
  4478. "foo.data" and "foo.rsrc" for input.
  4479. .PP
  4480. For output files,
  4481. .I mcvert
  4482. always uses the specified base file name and appropriate extension.
  4483. For MacBinary and BinHex 4.0 input files,
  4484. the base file name is specified within the input file,
  4485. while for plain files,
  4486. the file name specified on the command line is used.
  4487. The appropriate extension is based on the conversion,
  4488. or on the MAC_EXT
  4489. environment variable for MacBinary output files.
  4490. For example, if there is text file named foo.text
  4491. (but no file named foo),
  4492. "mcvert -u foo" will use foo.text as input, and
  4493. generate a file called "foo.bin",
  4494. while 
  4495. "mcvert -u foo.text" will use foo.text as input, and
  4496. generate a file called "foo.text.bin".
  4497. .SH "ENVIRONMENT VARIABLES AND DEFAULTS"
  4498. There are five environment variables one may use to customize 
  4499. the behavior of
  4500. .I mcvert
  4501. slightly.
  4502. .TP
  4503. .B MAC_FILETYPE
  4504. The file type of a MacBinary file converted from
  4505. non BinHex 4.0 inputs is set to this four-character sequence.
  4506. For example, one might
  4507. set this variable to "PICT" when converting files created
  4508. by ppmtopict(1).
  4509. The default is "TEXT" for Text or Host inputs, and "????" otherwise.
  4510. BinHex 4.0 inputs specify the file type to use internally.
  4511. .TP
  4512. .B MAC_EDITOR
  4513. The creator type (author)
  4514. of MacBinary files is set to this four-character sequence.
  4515. The default is "MACA" (the creator type of MacWrite)
  4516. for Text inputs, and "????" otherwise.
  4517. BinHex 4.0 inputs specify the creator type to use internally.
  4518. .TP
  4519. .B MAC_DLOAD_DIR
  4520. The MacBinary files created when option -D is selected are placed in this
  4521. directory.  The default is ".", the current working directory.
  4522. .TP
  4523. .B MAC_EXT
  4524. The MacBinary files created when option -D is selected are named according
  4525. to the file name field stored in the file header, with the name extended by
  4526. this suffix.  The default is ".bin".
  4527. .TP
  4528. .B MAC_LINE_LIMIT
  4529. The BinHex 4.0 files created when option -U is selected may be no longer than
  4530. this many lines long.  Files that would otherwise exceed this line limit
  4531. are broken up into several files with numbers embedded into their file 
  4532. names to show their order.  Each such file has "Start of part x" and "End
  4533. of part x" messages included where appropriate.
  4534. .SH BUGS
  4535. .PP
  4536. .I mcvert
  4537. silently discards input lines which are not completely valid.
  4538. Therefore, error indications for illegally formatted files are likely to
  4539. be somewhat obtuse, often with just a CRC mismatch message.
  4540. .PP
  4541. In order to handle files
  4542. (such as segmented comp.binaries.mac files)
  4543. which have extraneous
  4544. but valid BinHex 4.0 lines
  4545. (such as  "---"),
  4546. .I mcvert
  4547. uses the following heuristic
  4548. to discard suspect but legal lines
  4549. in BinHex 4.0 formatted input files.
  4550. When a new file is opened, or when invalid lines are found,
  4551. the search for good data begins.
  4552. While searching for good data,
  4553. if a line is too short (less than 12 characters),
  4554. or if a line is just
  4555. a single repeated character, the line is discarded.
  4556. Once
  4557. .I mcvert
  4558. starts processing good data,
  4559. no valid lines are discarded.
  4560. Thus, this heuristic can also discard (unusually formatted)
  4561. valid and intended BinHex 4.0 lines.
  4562. While there is no way to tune the heuristic
  4563. (other than modifying the program and recompiling),
  4564. the heuristic can be completely disabled with the
  4565. .B -H
  4566. option.
  4567. So if you run into problems,
  4568. put all the relevant lines into one file,
  4569. edit the file to remove any extraneous lines,
  4570. and invoke
  4571. .I mcvert
  4572. with the
  4573. .B -H
  4574. option.
  4575. .PP
  4576. It should be possible to discard bad input now and successfully translate
  4577. good input later, but bad input usually causes immediate termination.
  4578. .PP
  4579. A more diligent person would support BinHex 3.0 and BinHex 2.0 and BinHex
  4580. 5000 B. C., but I've never seen or heard of anyone using them in years.
  4581. .SH "OTHER PROGRAMS"
  4582. There are a number of programs which run on the Mac and convert
  4583. between various Macintosh file formats.
  4584. For example, here's what info-mac/help/accessing-files.txt, as of 13Jun93,
  4585. has to say about converting between BinHex 4.0 and native Mac files:
  4586. .RS
  4587. X
  4588. You can also do the conversion on
  4589. your Macintosh by using any of a number of utilities, including BinHex
  4590. 4.0, StuffIt, or Compact Pro. We recommend using Compact Pro because
  4591. it is slightly more convenient and reliable than the other tools.
  4592. Note: do NOT use BinHex 5.0 as it is incompatible, for some very
  4593. brain-damaged reasons.
  4594. .RE
  4595. X
  4596. CompactPro is a wonderful piece of shareware.  But if your needs are
  4597. limited to expansion of BinHex 4.0 files, StuffIt or
  4598. CompactPro archives or AppleLink packages, then the freeware 
  4599. StuffIt Expander (v 3.0.3 as of 28Jul93) may be just what you want.
  4600. .PP
  4601. There are other programs available which run under UNIX and convert
  4602. between various Macintosh file formats.
  4603. One of these programs may be what you want to use if
  4604. .I mcvert
  4605. does not meet your needs.
  4606. One collection, called
  4607. .IR macutil ,
  4608. is available from various archives.
  4609. Here's what the comp.sys.mac.comm FAQ (Frequently Asked Questions),
  4610. Last-modified: Sat Jun 05 1993, has to say about it:
  4611. .RS
  4612. .IP "As of (8/92), macutil includes three programs:"
  4613. .IP hexbin
  4614. a program to convert BinHex 4.0 to MacBinary;
  4615. it also converts uuencode (and UULite) files to their
  4616. native binary format; support for .dl, .hex, and .hcx
  4617. formats (all predecessors of BinHex 4.0) also exists
  4618. .IP macsave
  4619. a MacBinary filter program to convert
  4620. between various MacBinary representations, including
  4621. a single .bin file, three separate .data, .rsrc, .info
  4622. files, and AUFS format. macsave also allows one to
  4623. "peek" inside MacBinary files
  4624. .IP macunpack
  4625. a program to unpack PackIt, StuffIt,
  4626. Diamond, Compactor/Compact Pro, most StuffIt Classic
  4627. and StuffIt Deluxe, DiskDoubler, Zoom and LHarc/MacLHa
  4628. archives.
  4629. X
  4630. It also decodes BinHex 5.0, MacBinary, uuencode, and
  4631. UNIX compress (ie: .Z suffix) files (as well as variants
  4632. of compress implemented by various Macintosh compress
  4633. programs).
  4634. X
  4635. Support for password protected and/or multi-segment
  4636. archives of various types is minimal or non-existent.
  4637. .RE
  4638. .SH "SEE ALSO"
  4639. hexbin(1),
  4640. kermit(1),
  4641. macbin(1),
  4642. macunpack(1),
  4643. macsave(1),
  4644. macutil(1),
  4645. ppmtopict(1),
  4646. sit(1),
  4647. unsit(1),
  4648. xbin(1),
  4649. xmodem(1)
  4650. .SH AUTHORS
  4651. Doug Moore, Cornell University Computer Science.  Based upon
  4652. .I xbin
  4653. by Dave Johnson, Brown University, as modified by Guido van Rossum, and upon
  4654. .I unpit
  4655. by Allan G. Weber, as well as upon correspondence with several helpful
  4656. readers of USENET.
  4657. .PP
  4658. Joseph P. Skudlarek (Jskud@wv.MentorG.com) made numerous
  4659. enhancement and maintenance releases.
  4660. See the comments in mcvert.c for additional supporting characters.
  4661. SHAR_EOF
  4662. chmod 0444 mcvert.1 ||
  4663. echo 'restore of mcvert.1 failed'
  4664. Wc_c="`wc -c < 'mcvert.1'`"
  4665. test 13789 -eq "$Wc_c" ||
  4666.     echo 'mcvert.1: original size 13789, current size' "$Wc_c"
  4667. fi
  4668. # ============= mcvert.man ==============
  4669. if test -f 'mcvert.man' -a X"$1" != X"-c"; then
  4670.     echo 'x - skipping mcvert.man (File already exists)'
  4671. else
  4672. echo 'x - extracting mcvert.man (Text)'
  4673. sed 's/^X//' << 'SHAR_EOF' > 'mcvert.man' &&
  4674. X
  4675. X
  4676. X
  4677. X MCVERT(LOCAL)                                                 MCVERT(LOCAL)
  4678. X                                   10Nov93
  4679. X
  4680. X
  4681. X
  4682. X NAME
  4683. X      mcvert - MacBinary <=> BinHex 4.0 and more file conversion utility
  4684. X
  4685. X SYNOPSIS
  4686. X      mcvert { [option] ... name ... } ...
  4687. X
  4688. X DESCRIPTION
  4689. X      The mcvert program translates files between MacBinary format and other
  4690. X      formats often used in exchanging Macintosh files.  See FILE FORMATS
  4691. X      below for a description of the file formats supported.
  4692. X
  4693. X PARAMETERS
  4694. X      The defaults for the parameters are -xDqv: convert BinHex 4.0 files
  4695. X      (x) to MacBinary files (D), bypass automatic unpacking of PIT files
  4696. X      (q), and provide a verbose level of output (v).
  4697. X
  4698. X OPTIONS
  4699. X      All the options, other than FORMAT OPTIONS described below, are listed
  4700. X      here.  From each set, one and only one alternative is active for any
  4701. X      one file.
  4702. X
  4703. X      U | D
  4704. X           When option -U, as in Upload, is selected, the conversion is from
  4705. X           MacBinary to something else.  Conversely, option -D, as in
  4706. X           Download, selects conversion from something to MacBinary.
  4707. X
  4708. X      p | q
  4709. X           If a BinHex 4.0 to MacBinary conversion is taking place and
  4710. X           option -p, as in Pit, is selected, any file of type "PIT " will
  4711. X           be unpacked into its constituent parts.  This option does not
  4712. X           recursively unpack "PIT " files packed in "PIT " files.  If a
  4713. X           MacBinary to BinHex 4.0 conversion is taking place, this option
  4714. X           is currently ignored.  Conversely, option -q, as in Quiescent,
  4715. X           does no such unpacking.
  4716. X
  4717. X      t    Macintosh and UNIX differ in the end-of-line character they use.
  4718. X           Option -t, as in Translate, enables end-of-line character
  4719. X           translation for the data.  Translation is off by default, but it
  4720. X           is enabled automatically when processing -u (Usual Text) files.
  4721. X           Option -t is useful when processing both data and resource files
  4722. X           at the same time (option -b) to enable end-of-line character
  4723. X           translation for the data.
  4724. X
  4725. X      S | s | v | V | VV
  4726. X           Normally, mcvert prints converting messages and other information
  4727. X           about the files it is processing to stderr.  Option -S, as in
  4728. X           SILENT, disables all such reporting.  Option -s, as in Silent,
  4729. X           disables all but the "Converting ..." messages.  Option -v, as in
  4730. X           Verbose, emits generally useful information.  Option -V, as in
  4731. X           VERBOSE, displays some additional debugging information.  Option
  4732. X           -VV, as in VERY VERBOSE, displays detailed debugging information
  4733. X
  4734. X
  4735. X
  4736. X                                    - 1 -      Formatted:  November 15, 1993
  4737. X
  4738. X
  4739. X
  4740. X
  4741. X
  4742. X
  4743. X MCVERT(LOCAL)                                                 MCVERT(LOCAL)
  4744. X                                   10Nov93
  4745. X
  4746. X
  4747. X
  4748. X           as well.
  4749. X
  4750. X      H    Option -H, as in Heuristic, disables the skip-legal-but-suspect-
  4751. X           lines heuristic used when processing BinHex 4.0 formatted input
  4752. X           files.  See BUGS below for details on the heuristic.
  4753. X
  4754. X      I    Option -I, as in Information only, does not write output files,
  4755. X           but does indicate which output files would normally be written.
  4756. X           All other operations are performed, including verifying file
  4757. X           formats and calculated CRC values.  The -I option basically
  4758. X           provides a non-destructive verification of the files and their
  4759. X           processing.  It is also a soothing balm for the somewhat
  4760. X           paranoid, since it reports what files would be changed, without
  4761. X           actually changing them.
  4762. X
  4763. X      P    Option -P, as in Pipe output to stdout, writes the resulting
  4764. X           output file(s) to stdout, rather than to the file system with the
  4765. X           appropriate extension.  The default is to use the file system.
  4766. X
  4767. X FILE FORMATS
  4768. X      Some useful formats in which Macintosh files are represented on non-
  4769. X      Macs are:
  4770. X
  4771. X      MacBinary:
  4772. X           An eight bit wide representation of the data and resource forks
  4773. X           of a Mac file and of relevant Finder information, MacBinary files
  4774. X           are recognized as "special" by several Macintosh terminal
  4775. X           emulators.  These emulators, using kermit or xmodem or other file
  4776. X           transfer protocols, can separate the incoming file into forks and
  4777. X           appropriately modify the Desktop to display icons, types,
  4778. X           creation dates, and the like.
  4779. X
  4780. X      BinHex 4.0:
  4781. X           A seven bit wide representation of a Mac file with CRC error
  4782. X           checking, BinHex 4.0 files are designed for communication of Mac
  4783. X           files over long distance, possibly noisy, seven bit wide paths.
  4784. X
  4785. X      PackIt:
  4786. X           PackIt files are actually representations of collections of Mac
  4787. X           files, possibly Huffman compressed.  Packing many small related
  4788. X           files together before a MacBinary transfer or a translation to
  4789. X           BinHex 4.0 is common practice.
  4790. X
  4791. X      Text:
  4792. X           A Macintosh ends each line of a plain text file with a carriage
  4793. X           return character (^M), rather than the newline character (^J)
  4794. X           that some systems require (for example, UNIX).  Moreover, a
  4795. X           MacBinary file has prepended Finder information that non-
  4796. X           Macintoshes usually don't expect.
  4797. X
  4798. X
  4799. X
  4800. X
  4801. X
  4802. X                                    - 2 -      Formatted:  November 15, 1993
  4803. X
  4804. X
  4805. X
  4806. X
  4807. X
  4808. X
  4809. X MCVERT(LOCAL)                                                 MCVERT(LOCAL)
  4810. X                                   10Nov93
  4811. X
  4812. X
  4813. X
  4814. X      Data, Rsrc:
  4815. X           A Data or Rsrc file is the exact copy of the data or resource
  4816. X           fork of a Macintosh file.
  4817. X
  4818. X FORMAT OPTIONS
  4819. X      Exactly one of the following selections may be specified for an input
  4820. X      name:
  4821. X
  4822. X      x    BinHex 4.0 [.hqx] - files in the MacBinary format are translated
  4823. X           to BinHex 4.0 files, or vice versa.  The name argument is the
  4824. X           name of a file to be converted.  If the conversion is from BinHex
  4825. X           4.0 to MacBinary, several files may comprise the BinHex 4.0
  4826. X           representation of the Mac file.  Rather than manually concatenate
  4827. X           the files and manually delete mail headers and other extraneous
  4828. X           garbage, one may specify the names of the files in order and
  4829. X           mcvert will do the concatenating and deleting.  Conversely, in
  4830. X           converting a MacBinary file to BinHex 4.0 format for mailing over
  4831. X           long distances, one may be restricted to mail messages of no
  4832. X           greater that some fixed length.  In this case, mcvert can
  4833. X           automatically divide the BinHex 4.0 file into pieces and label
  4834. X           each piece appropriately.  For details on automatically
  4835. X           segmenting files, see the description of the MAC_LINE_LIMIT
  4836. X           environment variable below.
  4837. X
  4838. X      u | h
  4839. X           Text [.text] - files in the MacBinary format with nonempty data
  4840. X           forks and empty resource forks are made from ordinary data files,
  4841. X           or vice versa.  Option -u, for Usual Text, performs translation.
  4842. X           Option -h, for Host Text, performs no translation.  When
  4843. X           translating, UNIX newline characters are interchanged with
  4844. X           Macintosh carriage return characters.
  4845. X
  4846. X      d    Data [.data] - files in the MacBinary format with nonempty data
  4847. X           forks and empty resource forks are made from ordinary data files,
  4848. X           or vice versa.  If the data is really text, you should use -u or
  4849. X           -h so that the file type and creator get set correctly.
  4850. X
  4851. X      r    Resource [.rsrc] - files in the MacBinary format with empty data
  4852. X           forks and nonempty resource forks are made from ordinary data
  4853. X           files, or vice versa.
  4854. X
  4855. X      b    Both [.data .rsrc] - files in the MacBinary format with nonempty
  4856. X           data forks and and nonempty resource forks are made from ordinary
  4857. X           data files, or vice versa.  For option -b processing, a single
  4858. X           base file name is provided, and the ".data" and ".rsrc"
  4859. X           extensions are supplied by mcvert.
  4860. X
  4861. X FILE NAMES AND EXTENSIONS
  4862. X      mcvert uses certain file extensions when reading and writing files.
  4863. X      These extensions are indicated in the "FORMAT OPTIONS" section above.
  4864. X      For example, the appropriate extension for a BinHex 4.0 file is
  4865. X
  4866. X
  4867. X
  4868. X                                    - 3 -      Formatted:  November 15, 1993
  4869. X
  4870. X
  4871. X
  4872. X
  4873. X
  4874. X
  4875. X MCVERT(LOCAL)                                                 MCVERT(LOCAL)
  4876. X                                   10Nov93
  4877. X
  4878. X
  4879. X
  4880. X      ".hqx".
  4881. X
  4882. X      For input files, mcvert first tries to open the file using the
  4883. X      specified name.  If that fails, mcvert appends the appropriate suffix
  4884. X      (if not already present) and tries again.  Recall that for option -b
  4885. X      (Both) processing, a single base file name must be provided, since the
  4886. X      ".data" and ".rsrc" extensions are appended automatically by mcvert.
  4887. X      For example, "mcvert foo" will try to open "foo", and failing that,
  4888. X      try to open "foo.hqx" for input; while "mcvert -b foo" will open only
  4889. X      "foo.data" and "foo.rsrc" for input.
  4890. X
  4891. X      For output files, mcvert always uses the specified base file name and
  4892. X      appropriate extension.  For MacBinary and BinHex 4.0 input files, the
  4893. X      base file name is specified within the input file, while for plain
  4894. X      files, the file name specified on the command line is used.  The
  4895. X      appropriate extension is based on the conversion, or on the MAC_EXT
  4896. X      environment variable for MacBinary output files.  For example, if
  4897. X      there is text file named foo.text (but no file named foo), "mcvert -u
  4898. X      foo" will use foo.text as input, and generate a file called "foo.bin",
  4899. X      while "mcvert -u foo.text" will use foo.text as input, and generate a
  4900. X      file called "foo.text.bin".
  4901. X
  4902. X ENVIRONMENT VARIABLES AND DEFAULTS
  4903. X      There are five environment variables one may use to customize the
  4904. X      behavior of mcvert slightly.
  4905. X
  4906. X      MAC_FILETYPE
  4907. X           The file type of a MacBinary file converted from non BinHex 4.0
  4908. X           inputs is set to this four-character sequence.  For example, one
  4909. X           might set this variable to "PICT" when converting files created
  4910. X           by ppmtopict(1).  The default is "TEXT" for Text or Host inputs,
  4911. X           and "????" otherwise.  BinHex 4.0 inputs specify the file type to
  4912. X           use internally.
  4913. X
  4914. X      MAC_EDITOR
  4915. X           The creator type (author) of MacBinary files is set to this
  4916. X           four-character sequence.  The default is "MACA" (the creator type
  4917. X           of MacWrite) for Text inputs, and "????" otherwise.  BinHex 4.0
  4918. X           inputs specify the creator type to use internally.
  4919. X
  4920. X      MAC_DLOAD_DIR
  4921. X           The MacBinary files created when option -D is selected are placed
  4922. X           in this directory.  The default is ".", the current working
  4923. X           directory.
  4924. X
  4925. X      MAC_EXT
  4926. X           The MacBinary files created when option -D is selected are named
  4927. X           according to the file name field stored in the file header, with
  4928. X           the name extended by this suffix.  The default is ".bin".
  4929. X
  4930. X
  4931. X
  4932. X
  4933. X
  4934. X                                    - 4 -      Formatted:  November 15, 1993
  4935. X
  4936. X
  4937. X
  4938. X
  4939. X
  4940. X
  4941. X MCVERT(LOCAL)                                                 MCVERT(LOCAL)
  4942. X                                   10Nov93
  4943. X
  4944. X
  4945. X
  4946. X      MAC_LINE_LIMIT
  4947. X           The BinHex 4.0 files created when option -U is selected may be no
  4948. X           longer than this many lines long.  Files that would otherwise
  4949. X           exceed this line limit are broken up into several files with
  4950. X           numbers embedded into their file names to show their order.  Each
  4951. X           such file has "Start of part x" and "End of part x" messages
  4952. X           included where appropriate.
  4953. X
  4954. X BUGS
  4955. X      mcvert silently discards input lines which are not completely valid.
  4956. X      Therefore, error indications for illegally formatted files are likely
  4957. X      to be somewhat obtuse, often with just a CRC mismatch message.
  4958. X
  4959. X      In order to handle files (such as segmented comp.binaries.mac files)
  4960. X      which have extraneous but valid BinHex 4.0 lines (such as  "---"),
  4961. X      mcvert uses the following heuristic to discard suspect but legal lines
  4962. X      in BinHex 4.0 formatted input files.  When a new file is opened, or
  4963. X      when invalid lines are found, the search for good data begins.  While
  4964. X      searching for good data, if a line is too short (less than 12
  4965. X      characters), or if a line is just a single repeated character, the
  4966. X      line is discarded.  Once mcvert starts processing good data, no valid
  4967. X      lines are discarded.  Thus, this heuristic can also discard (unusually
  4968. X      formatted) valid and intended BinHex 4.0 lines.  While there is no way
  4969. X      to tune the heuristic (other than modifying the program and
  4970. X      recompiling), the heuristic can be completely disabled with the -H
  4971. X      option.  So if you run into problems, put all the relevant lines into
  4972. X      one file, edit the file to remove any extraneous lines, and invoke
  4973. X      mcvert with the -H option.
  4974. X
  4975. X      It should be possible to discard bad input now and successfully
  4976. X      translate good input later, but bad input usually causes immediate
  4977. X      termination.
  4978. X
  4979. X      A more diligent person would support BinHex 3.0 and BinHex 2.0 and
  4980. X      BinHex 5000 B. C., but I've never seen or heard of anyone using them
  4981. X      in years.
  4982. X
  4983. X OTHER PROGRAMS
  4984. X      There are a number of programs which run on the Mac and convert
  4985. X      between various Macintosh file formats.  For example, here's what
  4986. X      info-mac/help/accessing-files.txt, as of 13Jun93, has to say about
  4987. X      converting between BinHex 4.0 and native Mac files:
  4988. X
  4989. X           You can also do the conversion on your Macintosh by using any of
  4990. X           a number of utilities, including BinHex 4.0, StuffIt, or Compact
  4991. X           Pro. We recommend using Compact Pro because it is slightly more
  4992. X           convenient and reliable than the other tools.  Note: do NOT use
  4993. X           BinHex 5.0 as it is incompatible, for some very brain-damaged
  4994. X           reasons.
  4995. X
  4996. X      CompactPro is a wonderful piece of shareware.  But if your needs are
  4997. X
  4998. X
  4999. X
  5000. X                                    - 5 -      Formatted:  November 15, 1993
  5001. X
  5002. X
  5003. X
  5004. X
  5005. X
  5006. X
  5007. X MCVERT(LOCAL)                                                 MCVERT(LOCAL)
  5008. X                                   10Nov93
  5009. X
  5010. X
  5011. X
  5012. X      limited to expansion of BinHex 4.0 files, StuffIt or CompactPro
  5013. X      archives or AppleLink packages, then the freeware StuffIt Expander (v
  5014. X      3.0.3 as of 28Jul93) may be just what you want.
  5015. X
  5016. X      There are other programs available which run under UNIX and convert
  5017. X      between various Macintosh file formats.  One of these programs may be
  5018. X      what you want to use if mcvert does not meet your needs.  One
  5019. X      collection, called macutil, is available from various archives.
  5020. X      Here's what the comp.sys.mac.comm FAQ (Frequently Asked Questions),
  5021. X      Last-modified: Sat Jun 05 1993, has to say about it:
  5022. X
  5023. X           As of (8/92), macutil includes three programs:
  5024. X
  5025. X           hexbin
  5026. X                a program to convert BinHex 4.0 to MacBinary; it also
  5027. X                converts uuencode (and UULite) files to their native binary
  5028. X                format; support for .dl, .hex, and .hcx formats (all
  5029. X                predecessors of BinHex 4.0) also exists
  5030. X
  5031. X           macsave
  5032. X                a MacBinary filter program to convert between various
  5033. X                MacBinary representations, including a single .bin file,
  5034. X                three separate .data, .rsrc, .info files, and AUFS format.
  5035. X                macsave also allows one to "peek" inside MacBinary files
  5036. X
  5037. X           macunpack
  5038. X                a program to unpack PackIt, StuffIt, Diamond,
  5039. X                Compactor/Compact Pro, most StuffIt Classic and StuffIt
  5040. X                Deluxe, DiskDoubler, Zoom and LHarc/MacLHa archives.
  5041. X
  5042. X                It also decodes BinHex 5.0, MacBinary, uuencode, and UNIX
  5043. X                compress (ie: .Z suffix) files (as well as variants of
  5044. X                compress implemented by various Macintosh compress
  5045. X                programs).
  5046. X
  5047. X                Support for password protected and/or multi-segment archives
  5048. X                of various types is minimal or non-existent.
  5049. X
  5050. X SEE ALSO
  5051. X      hexbin(1), kermit(1), macbin(1), macunpack(1), macsave(1), macutil(1),
  5052. X      ppmtopict(1), sit(1), unsit(1), xbin(1), xmodem(1)
  5053. X
  5054. X AUTHORS
  5055. X      Doug Moore, Cornell University Computer Science.  Based upon xbin by
  5056. X      Dave Johnson, Brown University, as modified by Guido van Rossum, and
  5057. X      upon unpit by Allan G. Weber, as well as upon correspondence with
  5058. X      several helpful readers of USENET.
  5059. X
  5060. X      Joseph P. Skudlarek (Jskud@wv.MentorG.com) made numerous enhancement
  5061. X      and maintenance releases.  See the comments in mcvert.c for additional
  5062. X      supporting characters.
  5063. X
  5064. X
  5065. X
  5066. X                                    - 6 -      Formatted:  November 15, 1993
  5067. X
  5068. X
  5069. X
  5070. SHAR_EOF
  5071. chmod 0644 mcvert.man ||
  5072. echo 'restore of mcvert.man failed'
  5073. Wc_c="`wc -c < 'mcvert.man'`"
  5074. test 16929 -eq "$Wc_c" ||
  5075.     echo 'mcvert.man: original size 16929, current size' "$Wc_c"
  5076. fi
  5077. exit 0
  5078.  
  5079. ----------------------------------------------------------------------------
  5080. Joseph Skudlarek  Mentor Graphics  8005 SW Boeckman Rd  Wilsonville OR 97070
  5081. (503) 685-1576 (work)
  5082. {Jskud@wv.MentorG.com,Joseph_Skudlarek@MentorG.com}
  5083.  
  5084.  
  5085.